Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Gdy system ochrony danych jest inicjowany, stosuje ustawienia domyślne na podstawie środowiska operacyjnego. Te ustawienia są odpowiednie dla aplikacji działających na jednej maszynie. Istnieją jednak przypadki, w których deweloper może chcieć zmienić ustawienia domyślne:
- Aplikacja jest rozłożona na wiele maszyn.
- Ze względów zgodności.
W tych scenariuszach system ochrony danych oferuje zaawansowany interfejs API konfiguracji.
Ostrzeżenie
Podobnie jak w przypadku plików konfiguracji pierścień kluczy ochrony danych powinien być chroniony przy użyciu odpowiednich uprawnień. Możesz wybrać szyfrowanie kluczy w stanie spoczynku, ale nie uniemożliwia to cyberatakom tworzenia nowych kluczy. W związku z tym ma to wpływ na bezpieczeństwo aplikacji. Lokalizacja magazynu skonfigurowana przy użyciu usługi Data Protection powinna mieć ograniczony dostęp do samej aplikacji, podobnie jak w przypadku ochrony plików konfiguracji. Jeśli na przykład zdecydujesz się przechowywać pierścień kluczy na dysku, użyj uprawnień systemu plików. Upewnij się, że tylko tożsamość, w ramach której działa aplikacja internetowa, ma dostęp do odczytu, zapisu i tworzenia dostępu do tego katalogu. Jeśli używasz usługi Azure Blob Storage, tylko aplikacja internetowa powinna mieć możliwość odczytu, zapisu lub tworzenia nowych wpisów w magazynie obiektów blob itp.
Metoda rozszerzenia AddDataProtection zwraca IDataProtectionBuilder.
IDataProtectionBuilder
Uwidacznia metody rozszerzeń, które można połączyć w celu skonfigurowania opcji ochrony danych.
Uwaga
Ten artykuł został napisany dla aplikacji działającej w kontenerze platformy Docker. W kontenerze Docker aplikacja zawsze ma tę samą ścieżkę i dlatego ten sam identyfikator aplikacji. Aplikacje, które muszą działać w wielu środowiskach (na przykład lokalnym i wdrożonym), muszą ustawić domyślny rozróżniacz aplikacji dla środowiska. Uruchamianie aplikacji w wielu środowiskach wykracza poza zakres tego artykułu.
Następujące pakiety NuGet są wymagane dla rozszerzeń ochrony danych używanych w tym artykule:
Ochrona kluczy za pomocą usługi Azure Key Vault (ProtectKeysWithAzureKeyVault
)
Aby lokalnie korzystać z Azure Key Vault przy użyciu poświadczeń dewelopera, zaloguj się do konta magazynu w programie Visual Studio lub zaloguj się przy użyciu Azure CLI. Jeśli jeszcze nie zainstalowano interfejsu wiersza polecenia platformy Azure, zobacz Jak zainstalować interfejs wiersza polecenia platformy Azure. Następujące polecenie można wykonać w panelu PowerShella dla deweloperów w programie Visual Studio lub w wierszu poleceń, gdy nie korzystasz z programu Visual Studio.
az login
Aby uzyskać więcej informacji, zobacz Logowanie do platformy Azure przy użyciu narzędzi deweloperskich.
Podczas tworzenia magazynu kluczy w portalu Entra lub Azure:
Skonfiguruj magazyn kluczy do używania kontroli dostępu opartej na rolach (RABC) platformy Azure. Jeśli nie korzystasz z usługi Azure Virtual Network, w tym na potrzeby lokalnego programowania i testowania, upewnij się, że dostęp publiczny w kroku Sieć jest włączony (zaznaczone). Włączenie dostępu publicznego uwidacznia tylko punkt końcowy magazynu kluczy. Uwierzytelnione konta są nadal wymagane do uzyskania dostępu.
Utwórz zarządzaną platformę Azure Identity (lub dodaj rolę do istniejącego Identity zarządzanego, którego zamierzasz użyć) z rolą użytkownika kryptograficznego usługi Key Vault . Przypisz Managed Identity do usługi Azure App Service, która hostuje wdrożenie: Ustawienia>Identity>Przypisane przez użytkownika>Dodaj.
Uwaga
Jeśli planujesz również lokalnie uruchomić aplikację z autoryzowanym użytkownikiem do dostępu do obiektów blob przy użyciu Azure CLI lub uwierzytelniania usługi platformy Azure programu Visual Studio, dodaj konto użytkownika platformy Azure dewelopera w obszarze Kontrola dostępu (IAM) z rolą Użytkownik Kryptograficzny Key Vault. Jeśli chcesz użyć Azure CLI za pośrednictwem programu Visual Studio, wykonaj polecenie
az login
z panelu Developer PowerShell i postępuj zgodnie z monitami, aby się uwierzytelnić w dzierżawie.Gdy szyfrowanie klucza jest aktywne, klucze w pliku klucza zawierają komentarz "This key is encrypted with Azure Key Vault." Po uruchomieniu aplikacji wybierz polecenie Wyświetl/edytuj z menu kontekstowego na końcu wiersza klucza, aby potwierdzić, że klucz jest obecny z zastosowanymi zabezpieczeniami magazynu kluczy.
Opcjonalnie można włączyć automatyczną rotację kluczy magazynu kluczy bez obaw o odszyfrowywanie ładunków przy użyciu kluczy ochrony danych na podstawie wygasłych/obróconych kluczy magazynu kluczy. Każdy wygenerowany klucz ochrony danych zawiera odwołanie do klucza magazynu kluczy używanego do jego zaszyfrowania. Upewnij się, że zachowasz klucze, które wygasły, nie usuwaj ich w Azure Key Vault. Ponadto należy użyć identyfikatora klucza bez wersji w konfiguracji magazynu kluczy aplikacji, gdzie identyfikator GUID klucza nie jest umieszczany na końcu identyfikatora (na przykład:
https://contoso.vault.azure.net/keys/data-protection
). Użyj podobnego okresu rotacji dla obu kluczy, przy czym klucz magazynu kluczy powinien obracać się częściej niż klucz ochrony danych, aby upewnić się, że nowy klucz magazynu kluczy jest używany w momencie rotacji klucza ochrony danych.
Ochrona kluczy za pomocą usługi Azure Key Vault implementuje funkcję IXmlEncryptor , która wyłącza ustawienia automatycznej ochrony danych, w tym lokalizację magazynu pierścienia kluczy. Aby skonfigurować dostawcę usługi Azure Blob Storage do przechowywania kluczy w magazynie obiektów blob, postępuj zgodnie z wytycznymi zawartymi w temacie Dostawcy magazynu kluczy w ASP.NET Core i wywołaj jedno z przeciążeń PersistKeysToAzureBlobStorage w aplikacji. W poniższym przykładzie użyto przeciążenia, które akceptuje URI dla obiektu blob i poświadczenie tokenu (TokenCredential), korzystając z Azure Managed Service Identity do kontroli dostępu na podstawie ról (RBAC).
Aby skonfigurować dostawcę usługi Azure Key Vault, wywołaj jedno z ProtectKeysWithAzureKeyVault przeciążeń. Poniższy przykład używa przeciążenia, które akceptuje identyfikator klucza i poświadczenie tokenu (TokenCredential), korzystając z funkcji Zarządzanej Identity na potrzeby kontroli dostępu opartej na rolach w środowisku produkcyjnym (ManagedIdentityCredential) lub w czasie rozwoju i testowania DefaultAzureCredential. Inne przeciążenia akceptują klienta magazynu kluczy lub identyfikator klienta aplikacji z kluczem tajnym klienta. Aby uzyskać więcej informacji, zobacz Dostawcy magazynu kluczy dla platformy ASP.NET Core.
Aby uzyskać więcej informacji na temat interfejsu API i uwierzytelniania zestawu Azure SDK, zobacz Uwierzytelnianie aplikacji platformy .NET w usługach platformy Azure przy użyciu biblioteki platformy Azure Identity i Zapewnianie dostępu do kluczy, certyfikatów i wpisów tajnych przy użyciu kontroli dostępu opartej na rolach platformy Azure. Aby uzyskać wskazówki dotyczące rejestrowania, zobacz Rejestrowanie przy użyciu zestawu Azure SDK dla platformy .NET: rejestrowanie bez rejestracji klienta. W przypadku aplikacji korzystających z wstrzykiwania zależności aplikacja może wywołać AddAzureClientsCore, przekazując true
dla enableLogForwarding
, w celu utworzenia i połączenia infrastruktury logowania.
W pliku, w Program
którym są zarejestrowane usługi:
TokenCredential? credential;
if (builder.Environment.IsProduction())
{
credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
// Local development and testing only
DefaultAzureCredentialOptions options = new()
{
// Specify the tenant ID to use the dev credentials when running the app locally
// in Visual Studio.
VisualStudioTenantId = "{TENANT ID}",
SharedTokenCacheTenantId = "{TENANT ID}"
};
credential = new DefaultAzureCredential(options);
}
builder.Services.AddDataProtection()
.SetApplicationName("{APPLICATION NAME}")
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);
{MANAGED IDENTITY CLIENT ID}
: identyfikator klienta zarządzanego Identity platformy Azure (GUID).
{TENANT ID}
: Identyfikator najemcy.
{APPLICATION NAME}
: SetApplicationName ustawia unikatową nazwę tej aplikacji w systemie ochrony danych. Wartość powinna być zgodna z wdrożeniami aplikacji.
{BLOB URI}
: pełny identyfikator URI do pliku klucza. Identyfikator URI jest generowany przez usługę Azure Storage podczas tworzenia pliku klucza. Nie używaj SAS.
{KEY IDENTIFIER}
: identyfikator klucza usługi Azure Key Vault używany do szyfrowania kluczy. Zasady dostępu umożliwiają aplikacji dostęp do magazynu kluczy z uprawnieniami Get
, Unwrap Key
i Wrap Key
. Wersja klucza jest uzyskiwana po jego utworzeniu w portalu Entra lub Azure. Jeśli włączysz automatyczną rotację klucza magazynu kluczy, upewnij się, że używasz identyfikatora klucza bez wersji w konfiguracji magazynu kluczy aplikacji, czyli takiego, który nie zawiera na końcu identyfikatora GUID klucza (na przykład: https://contoso.vault.azure.net/keys/data-protection
).
Aby aplikacja komunikowała się i autoryzować się za pomocą usługi Azure Key Vault, Azure.Identity
pakiet NuGet musi być przywołyny przez aplikację.
Uwaga
Aby uzyskać wskazówki dotyczące dodawania pakietów do aplikacji .NET, zobacz artykuły w Instalowanie i zarządzanie pakietami oraz w proces korzystania z pakietów (dokumentacja NuGet). Sprawdź prawidłowe wersje pakietów pod adresem NuGet.org.
Uwaga
W środowiskach nieprodukcyjnych w poprzednim przykładzie użyto DefaultAzureCredential metody upraszczania uwierzytelniania podczas opracowywania aplikacji wdrażanych na platformie Azure przez połączenie poświadczeń używanych w środowiskach hostingu platformy Azure z poświadczeniami używanymi w środowisku lokalnym. Aby uzyskać więcej informacji, zobacz Uwierzytelnianie aplikacji platformy .NET hostowanych na platformie Azure do zasobów platformy Azure przy użyciu tożsamości zarządzanej przypisanej przez system.
Jeśli aplikacja używa starszych pakietów platformy Azure (Microsoft.AspNetCore.DataProtection.AzureStorage
i Microsoft.AspNetCore.DataProtection.AzureKeyVault
), zalecamy usunięcie tych odwołań i uaktualnienie do Azure.Extensions.AspNetCore.DataProtection.Blobs
pakietów i Azure.Extensions.AspNetCore.DataProtection.Keys
. Nowsze pakiety dotyczą kluczowych problemów z zabezpieczeniami i stabilnością.
Alternatywna metoda sygnatury dostępu współdzielonego (SAS): zamiast używać zarządzanego do dostępu do klucza obiektu blob w usłudze Azure Blob Storage, można wywołać przeciążenie Identity, które przyjmuje URI obiektu blob z tokenem SAS. Poniższy przykład nadal używa elementu (ManagedIdentityCredential produkcyjnego) lub (DefaultAzureCredential rozwojowego i testowania) dla elementu TokenCredential, jak pokazano w poprzednim przykładzie.
builder.Services.AddDataProtection()
.SetApplicationName("{APPLICATION NAME}")
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS}"))
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);
{APPLICATION NAME}
: SetApplicationName ustawia unikatową nazwę tej aplikacji w systemie ochrony danych. Wartość powinna być zgodna z wdrożeniami aplikacji.
{BLOB URI WITH SAS}
: Pełny identyfikator URI, w którym plik klucza powinien być przechowywany, wraz z tokenem SAS, jako parametr ciągu zapytania. Identyfikator URI jest generowany przez usługę Azure Storage w momencie, gdy żądasz sygnatury dostępu współdzielonego (SAS) dla przesłanego pliku klucza.
{KEY IDENTIFIER}
: identyfikator klucza usługi Azure Key Vault używany do szyfrowania kluczy. Zasady dostępu umożliwiają aplikacji dostęp do magazynu kluczy z uprawnieniami Get
, Unwrap Key
i Wrap Key
. Wersja klucza jest uzyskiwana po jego utworzeniu w portalu Entra lub Azure. Jeśli włączysz automatyczną rotację klucza magazynu kluczy, upewnij się, że używasz identyfikatora klucza bez wersji w konfiguracji magazynu kluczy aplikacji, czyli takiego, który nie zawiera na końcu identyfikatora GUID klucza (na przykład: https://contoso.vault.azure.net/keys/data-protection
).
Utrwalanie kluczy w systemie plików (PersistKeysToFileSystem
)
Aby przechowywać klucze w udziale UNC zamiast w domyślnej lokalizacji %LOCALAPPDATA% , skonfiguruj system za pomocą polecenia PersistKeysToFileSystem:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
Ostrzeżenie
Jeśli zmienisz lokalizację trwałości klucza, system nie będzie już automatycznie szyfrować kluczy magazynowanych, ponieważ nie wie, czy dpAPI jest odpowiednim mechanizmem szyfrowania.
Utrwalanie kluczy w bazie danych (PersistKeysToDbContext
)
Aby przechowywać klucze w bazie danych przy użyciu EntityFramework, skonfiguruj system za pomocą pakietu Microsoft.AspNetCore.DataProtection.EntityFrameworkCore :
builder.Services.AddDataProtection()
.PersistKeysToDbContext<SampleDbContext>();
Powyższy kod przechowuje klucze w skonfigurowanej bazie danych. Używany kontekst bazy danych musi implementować element IDataProtectionKeyContext
.
IDataProtectionKeyContext
uwidacznia właściwość DataProtectionKeys
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; } = null!;
Ta właściwość reprezentuje tabelę, w której są przechowywane klucze. Utwórz tabelę ręcznie lub za pomocą DbContext
funkcji Migracje. Aby uzyskać więcej informacji, zobacz DataProtectionKey.
Interfejs API do konfiguracji ochrony kluczy (ProtectKeysWith\*
)
Można skonfigurować system, aby chronił klucze w spoczynku, wywołując dowolne z ProtectKeysWith\*
API konfiguracji. Rozważmy poniższy przykład, który przechowuje klucze w udziale UNC i szyfruje klucze magazynowane przy użyciu określonego certyfikatu X.509.
Możesz dostarczyć X509Certificate2 do ProtectKeysWithCertificate z pliku, wywołując X509CertificateLoader.LoadCertificateFromFile:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]));
W poniższym przykładzie kodu pokazano, jak załadować certyfikat przy użyciu odcisku palca:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(builder.Configuration["CertificateThumbprint"]);
Możesz podać X509Certificate2 do ProtectKeysWithCertificate, taki jak certyfikat załadowany z pliku.
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]));
W poniższym przykładzie kodu pokazano, jak załadować certyfikat przy użyciu odcisku palca:
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(builder.Configuration["CertificateThumbprint"]);
Przykłady i omówienie wbudowanych mechanizmów szyfrowania kluczy można znaleźć w temacie Szyfrowanie kluczy magazynowanych w systemach Windows i Azure przy użyciu platformy ASP.NET Core.
Usuń ochronę kluczy z dowolnym certyfikatem (UnprotectKeysWithAnyCertificate
)
Certyfikaty można wymieniać, a klucze odszyfrowywać w stanie spoczynku, używając tablicy certyfikatów X509Certificate2 z UnprotectKeysWithAnyCertificate.
builder.Services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", builder.Configuration["CertificatePassword"]))
.UnprotectKeysWithAnyCertificate(
new X509Certificate2("certificate_1.pfx", builder.Configuration["CertificatePassword_1"]),
new X509Certificate2("certificate_2.pfx", builder.Configuration["CertificatePassword_2"]));
Ustawianie domyślnego okresu istnienia klucza (SetDefaultKeyLifetime
)
Aby skonfigurować system do używania okresu istnienia klucza 14 dni zamiast domyślnego 90 dni, użyj polecenia SetDefaultKeyLifetime:
builder.Services.AddDataProtection()
.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
Ustawianie nazwy aplikacji (SetApplicationName
)
Domyślnie system ochrony danych izoluje aplikacje od siebie na podstawie ścieżek głównych zawartości, nawet jeśli współużytkują to samo repozytorium kluczy fizycznych. Ta izolacja uniemożliwia aplikacjom zrozumienie chronionych ładunków innych aplikacji.
Aby udostępnić chronione ładunki między aplikacjami:
- W każdej aplikacji skonfiguruj SetApplicationName na tę samą wartość.
- Używaj tej samej wersji stosu Ochrony Danych API w aplikacjach. Wykonaj jedną z następujących czynności w plikach projektu aplikacji:
- Odwołuj się do tej samej wersji współdzielonego frameworku przez metapakiet Microsoft.AspNetCore.App.
- Odwołaj się do tej samej wersji pakietu Data Protection.
builder.Services.AddDataProtection()
.SetApplicationName("<sharedApplicationName>");
SetApplicationName program wewnętrznie ustawia wartość DataProtectionOptions.ApplicationDiscriminator. Dla celów rozwiązywania problemów, wartość przypisana dyskryminatorowi przez framework może być rejestrowana przy użyciu następującego kodu umieszczonego po zbudowaniu WebApplication w Program.cs
:
var discriminator = app.Services.GetRequiredService<IOptions<DataProtectionOptions>>()
.Value.ApplicationDiscriminator;
app.Logger.LogInformation("ApplicationDiscriminator: {ApplicationDiscriminator}", discriminator);
Aby uzyskać więcej informacji na temat sposobu użycia klasyfikatora, zobacz poniższe sekcje w dalszej części tego artykułu:
Ostrzeżenie
Na platformie .NET 6, WebApplicationBuilder normalizuje ścieżkę katalogu głównego zawartości, aby zakończyć ją znakiem DirectorySeparatorChar. Na przykład w systemie Windows ścieżka główna zawartości kończy się na \
i w systemie Linux /
. Inne hosty nie normalizują ścieżki. Większość aplikacji migrujących z HostBuilder lub WebHostBuilder nie będzie mieć tej samej nazwy aplikacji, ponieważ nie będą miały na końcu DirectorySeparatorChar
. Aby obejść ten problem, usuń znak separatora katalogu i ręcznie ustaw nazwę aplikacji, jak pokazano w poniższym kodzie:
using System.Reflection;
using Microsoft.AspNetCore.DataProtection;
var builder = WebApplication.CreateBuilder(args);
var trimmedContentRootPath =
builder.Environment.ContentRootPath.TrimEnd(Path.DirectorySeparatorChar);
builder.Services.AddDataProtection().SetApplicationName(trimmedContentRootPath);
var app = builder.Build();
app.MapGet("/", () => Assembly.GetEntryAssembly()!.GetName().Name);
app.Run();
Wyłączanie automatycznego generowania kluczy (DisableAutomaticKeyGeneration
)
Możesz mieć scenariusz, w którym nie chcesz, aby aplikacja automatycznie zamieniała klucze (tworzyła nowe klucze) w miarę zbliżania się do ich wygaśnięcia. Jednym z przykładów tego scenariusza mogą być aplikacje skonfigurowane w relacji podstawowej/pomocniczej, gdzie tylko podstawowa aplikacja jest odpowiedzialna za kluczowe problemy z zarządzaniem, a aplikacje pomocnicze mają po prostu widok pierścienia kluczy tylko do odczytu. Aplikacje pomocnicze można skonfigurować tak, aby traktować pierścień kluczy jako tylko do odczytu, konfigurując system przy użyciu polecenia DisableAutomaticKeyGeneration:
builder.Services.AddDataProtection()
.DisableAutomaticKeyGeneration();
Izolacja dla aplikacji
Gdy system ochrony danych jest dostarczany przez hosta ASP.NET Core, automatycznie izoluje aplikacje od siebie, nawet jeśli te aplikacje działają na tym samym koncie procesu roboczego i używają tego samego głównego materiału kluczowego. Jest to podobne do modyfikatora IsolateApps z elementu System.Web <machineKey>
.
Mechanizm izolacji działa, traktując każdą aplikację na komputerze lokalnym jako unikalną dzierżawę. W związku z tym IDataProtector dla danej aplikacji automatycznie uwzględnia identyfikator aplikacji jako wyróżnik (ApplicationDiscriminator). Unikatowy identyfikator aplikacji to ścieżka fizyczna aplikacji:
- W przypadku aplikacji hostowanych w usługach IIS unikatowy identyfikator to fizyczna ścieżka aplikacji w usługach IIS. Jeśli aplikacja jest wdrażana w środowisku farmy sieci Web, ta wartość jest stabilna przy założeniu, że środowiska usług IIS są podobnie skonfigurowane na wszystkich maszynach w farmie sieci Web.
- W przypadku aplikacji hostowanych samodzielnie na Kestrel serwerze unikatowy identyfikator to ścieżka fizyczna do aplikacji na dysku.
Unikatowy identyfikator jest przeznaczony do przetrwania resetowania — zarówno pojedynczej aplikacji, jak i samej maszyny.
Ten mechanizm izolacji zakłada, że aplikacje nie są złośliwe. Złośliwa aplikacja zawsze może mieć wpływ na dowolną inną aplikację działającą na tym samym koncie procesu roboczego. W udostępnionym środowisku hostingu, w którym aplikacje są wzajemnie niezaufane, dostawca hostingu powinien podjąć kroki w celu zapewnienia izolacji na poziomie systemu operacyjnego między aplikacjami, w tym oddzielenia bazowych repozytoriów kluczy aplikacji.
Jeśli system ochrony danych nie jest udostępniany przez hosta ASP.NET Core (na przykład, jeśli zostanie utworzony za pomocą konkretnego typu DataProtectionProvider
), izolacja aplikacji jest domyślnie wyłączona. Gdy izolacja aplikacji jest wyłączona, wszystkie aplikacje wspierane przez ten sam materiał kluczy mogą współdzielić ładunki, o ile zapewniają odpowiednie cele. Aby zapewnić izolację aplikacji w tym środowisku, wywołaj SetApplicationName
metodę w obiekcie konfiguracji i podaj unikatową nazwę dla każdej aplikacji.
Ochrona danych i izolacja aplikacji
Rozważ następujące kwestie dotyczące izolacji aplikacji:
Gdy wiele aplikacji jest wskazywanych na to samo repozytorium kluczy, intencją jest to, że aplikacje współużytkują ten sam materiał klucza głównego. Ochrona danych jest opracowywana przy założeniu, że wszystkie aplikacje współużytkujące pierścień kluczy mogą uzyskiwać dostęp do wszystkich elementów w tym pierścieniu kluczy. Unikatowy identyfikator aplikacji służy do izolowania kluczy specyficznych dla aplikacji pochodzących z kluczy dostarczonych przez pierścień kluczy. Nie oczekuje uprawnień na poziomie elementu, takich jak te udostępniane przez usługę Azure KeyVault do wymuszania dodatkowej izolacji. Próba uzyskania uprawnień na poziomie elementu powoduje wygenerowanie błędów aplikacji. Jeśli nie chcesz polegać na wbudowanej izolacji aplikacji, należy używać oddzielnych lokalizacji magazynu kluczy i nie udostępniać ich między aplikacjami.
Dyskryminator aplikacji (ApplicationDiscriminator) jest używany, aby umożliwić różnym aplikacjom współużytkowanie tego samego materiału klucza głównego, ale zachowanie odrębnych ładunków kryptograficznych dla każdej z nich. Aby aplikacje mogły wzajemnie odczytywać swoje ładunki kryptograficzne, muszą mieć ten sam identyfikator aplikacji, więc należy wywołać
SetApplicationName
.W przypadku naruszenia zabezpieczeń aplikacji (na przykład przez atak RCE), wszystkie materiały klucza głównego dostępne dla tej aplikacji muszą być również uznawane za naruszone, niezależnie od stanu ochrony w spoczynku. Oznacza to, że jeśli dwie aplikacje wskazują na to samo repozytorium, nawet jeśli korzystają z odmiennych identyfikatorów aplikacji, kompromitacja jednej z nich jest funkcjonalnie równoważna z kompromitacją obu.
Ta klauzula "funkcjonalnie równoważna dla kompromisu obu" obowiązuje nawet wtedy, gdy obie aplikacje używają różnych mechanizmów ochrony kluczy w spoczynku. Zazwyczaj nie jest to oczekiwana konfiguracja. Mechanizm ochrony danych w spoczynku ma zapewnić ochronę w przypadku, gdy cyberatak uzyska dostęp do odczytu do repozytorium. Atakujący, który uzyskuje dostęp do zapisu w repozytorium (być może dlatego, że uzyskał uprawnienia do wykonania kodu w aplikacji), może wstawić złośliwe klucze do archiwum. System ochrony danych celowo nie zapewnia ochrony przed cyberatakiem, który uzyskuje możliwość zapisu w repozytorium kluczy.
Jeśli aplikacje muszą pozostać naprawdę odizolowane od siebie, powinny używać różnych repozytoriów kluczy. To naturalnie wypada z definicji "izolowanej". Aplikacje nie są izolowane, jeśli wszystkie mają dostęp do odczytu i zapisu nawzajem do swoich magazynów danych.
Zmienianie algorytmów za pomocą polecenia UseCryptographicAlgorithms
Stos ochrony danych umożliwia zmianę domyślnego algorytmu używanego przez nowo wygenerowane klucze. Najprostszym sposobem wykonania tej czynności jest wywołanie UseCryptographicAlgorithms z funkcji zwrotnej konfiguracji.
builder.Services.AddDataProtection()
.UseCryptographicAlgorithms(new AuthenticatedEncryptorConfiguration
{
EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
});
Domyślnym algorytmem szyfrowania jest AES-256-CBC, a domyślnym algorytmem walidacji jest HMACSHA256. Zasady domyślne mogą być ustawiane przez administratora systemu za pośrednictwem zasad dla całej maszyny, ale jawne wywołanie UseCryptographicAlgorithms
zastąpi domyślne zasady.
Wywołanie UseCryptographicAlgorithms
umożliwia określenie żądanego algorytmu ze wstępnie zdefiniowanej wbudowanej listy. Nie musisz martwić się o implementację algorytmu. W powyższym scenariuszu system ochrony danych próbuje użyć implementacji CNG AES, jeśli jest uruchomiona w systemie Windows. W przeciwnym razie wraca do klasy zarządzanej System.Security.Cryptography.Aes .
Implementację można określić ręcznie za pomocą wywołania metody UseCustomCryptographicAlgorithms.
Napiwek
Zmiana algorytmów nie ma wpływu na istniejące klucze w pierścieniu kluczy. Dotyczy tylko nowo wygenerowanych kluczy.
Określanie niestandardowych algorytmów zarządzanych
Aby określić niestandardowe algorytmy zarządzane, utwórz ManagedAuthenticatedEncryptorConfiguration wystąpienie wskazujące typy implementacji:
builder.Services.AddDataProtection()
.UseCustomCryptographicAlgorithms(new ManagedAuthenticatedEncryptorConfiguration
{
// A type that subclasses SymmetricAlgorithm
EncryptionAlgorithmType = typeof(Aes),
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// A type that subclasses KeyedHashAlgorithm
ValidationAlgorithmType = typeof(HMACSHA256)
});
Ogólnie rzecz biorąc, właściwości *Type muszą wskazywać na konkretne, możliwe do zainicjowania (poprzez publiczny konstruktor bez parametrów) implementacje SymmetricAlgorithm i KeyedHashAlgorithm, chociaż system obsługuje specjalne przypadki niektórych wartości, takich jak typeof(Aes)
, dla wygody.
Uwaga
SymmetricAlgorithm musi mieć długość klucza ≥ 128 bitów i rozmiar bloku ≥ 64 bitów i musi obsługiwać szyfrowanie w trybie CBC za pomocą dopełnienia PKCS #7. Algorytm KeyedHashAlgorithm musi mieć rozmiar skrótu równy lub większy niż 128 bitów i musi obsługiwać klucze o długości równej długości skrótu algorytmu. KeyedHashAlgorithm nie jest ściśle wymagany do bycia HMAC.
Określanie niestandardowych algorytmów CNG systemu Windows
Aby określić niestandardowy algorytm CNG systemu Windows przy użyciu szyfrowania w trybie CBC z walidacją HMAC, utwórz CngCbcAuthenticatedEncryptorConfiguration wystąpienie zawierające informacje algorytmiczne:
builder.Services.AddDataProtection()
.UseCustomCryptographicAlgorithms(new CngCbcAuthenticatedEncryptorConfiguration
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// Passed to BCryptOpenAlgorithmProvider
HashAlgorithm = "SHA256",
HashAlgorithmProvider = null
});
Uwaga
Algorytm szyfrowania bloków symetrycznych musi mieć długość >klucza = 128 bitów, rozmiar >bloku = 64 bity i musi obsługiwać szyfrowanie w trybie CBC za pomocą dopełnienia PKCS #7. Algorytm skrótu musi mieć rozmiar skrótu >= 128 bitów i musi umożliwiać otwieranie za pomocą flagi BCRYPT_ALG_HANDLE_HMAC_FLAG. *Właściwości dostawcy można ustawić na wartość null, aby użyć domyślnego dostawcy dla określonego algorytmu. Aby uzyskać więcej informacji, zobacz dokumentację BCryptOpenAlgorithmProvider .
Aby określić niestandardowy algorytm CNG systemu Windows przy użyciu szyfrowania w trybie Galois/Counter z walidacją, utwórz instancję CngGcmAuthenticatedEncryptorConfiguration zawierającą informacje o algorytmie:
builder.Services.AddDataProtection()
.UseCustomCryptographicAlgorithms(new CngGcmAuthenticatedEncryptorConfiguration
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256
});
Uwaga
Algorytm szyfrowania bloków symetrycznych musi mieć długość >klucza = 128 bitów, rozmiar bloku o dokładnie 128 bitach i musi obsługiwać szyfrowanie GCM. Właściwość można ustawić na EncryptionAlgorithmProvider jako null, aby użyć domyślnego dostawcy dla danego algorytmu. Aby uzyskać więcej informacji, zobacz dokumentację BCryptOpenAlgorithmProvider .
Określanie innych algorytmów niestandardowych
Mimo że system ochrony danych nie jest uwidaczniony jako interfejs API pierwszej klasy, jest wystarczająco rozszerzalny, aby umożliwić określenie niemal dowolnego rodzaju algorytmu. ** Na przykład można zachować wszystkie klucze wewnątrz sprzętowego modułu zabezpieczeń (HSM) i zapewnić niestandardową implementację kluczowych procedur szyfrowania i deszyfrowania. Aby uzyskać więcej informacji, zobacz IAuthenticatedEncryptor w temacie Rozszerzalność kryptografii podstawowej.
Utrwalanie kluczy podczas hostowania w kontenerze platformy Docker
W przypadku hostowania w kontenerze Docker klucze powinny być przechowywane w jednym z następujących:
- Folder, który jest woluminem Dockera, przechowującym dane nawet po zakończeniu działania kontenera, na przykład jako wolumin udostępniony lub zamontowany na hoście.
- Dostawca zewnętrzny, taki jak Azure Blob Storage (pokazany w sekcji
ProtectKeysWithAzureKeyVault
) lub Redis.
Utrwalanie kluczy za pomocą usługi Redis
Do przechowywania kluczy powinny być używane tylko wersje usługi Redis obsługujące trwałość danych Redis. Usługa Azure Blob Storage jest trwała i może służyć do przechowywania kluczy. Aby uzyskać więcej informacji, zobacz ten problem w serwisie GitHub.
Przemysł drzewny
Włącz Information
lub niższy poziom rejestrowania, aby zdiagnozować problemy.
appsettings.json
Poniższy plik umożliwia rejestrowanie danych za pomocą interfejsu API ochrony danych.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning",
"Microsoft.AspNetCore.DataProtection": "Information"
}
},
"AllowedHosts": "*"
}
Aby uzyskać więcej informacji na temat rejestrowania, zobacz Rejestrowanie na platformie .NET Core i ASP.NET Core.
Dodatkowe zasoby
Gdy system ochrony danych jest inicjowany, stosuje ustawienia domyślne na podstawie środowiska operacyjnego. Te ustawienia są odpowiednie dla aplikacji działających na jednej maszynie. Istnieją jednak przypadki, w których deweloper może chcieć zmienić ustawienia domyślne:
- Aplikacja jest rozłożona na wiele maszyn.
- Ze względów zgodności.
W tych scenariuszach system ochrony danych oferuje zaawansowany interfejs API konfiguracji.
Ostrzeżenie
Podobnie jak w przypadku plików konfiguracji pierścień kluczy ochrony danych powinien być chroniony przy użyciu odpowiednich uprawnień. Możesz wybrać szyfrowanie kluczy w stanie spoczynku, ale nie uniemożliwia to cyberatakom tworzenia nowych kluczy. W związku z tym ma to wpływ na bezpieczeństwo aplikacji. Lokalizacja magazynu skonfigurowana przy użyciu usługi Data Protection powinna mieć ograniczony dostęp do samej aplikacji, podobnie jak w przypadku ochrony plików konfiguracji. Jeśli na przykład zdecydujesz się przechowywać pierścień kluczy na dysku, użyj uprawnień systemu plików. Upewnij się, że tylko tożsamość, w ramach której działa aplikacja internetowa, ma dostęp do odczytu, zapisu i tworzenia dostępu do tego katalogu. Jeśli używasz usługi Azure Blob Storage, tylko aplikacja internetowa powinna mieć możliwość odczytu, zapisu lub tworzenia nowych wpisów w blob store.
Metoda rozszerzenia zwraca metodę AddDataProtectionIDataProtectionBuilder, która uwidacznia metody rozszerzenia, które można połączyć w celu skonfigurowania opcji ochrony danych.
Następujące pakiety NuGet są wymagane dla rozszerzeń ochrony danych używanych w tym artykule:
Uwaga
Aby uzyskać wskazówki dotyczące dodawania pakietów do aplikacji .NET, zobacz artykuły w Instalowanie i zarządzanie pakietami oraz w proces korzystania z pakietów (dokumentacja NuGet). Sprawdź prawidłowe wersje pakietów pod adresem NuGet.org.
Ochrona kluczy za pomocą usługi Azure Key Vault (ProtectKeysWithAzureKeyVault
)
Aby lokalnie korzystać z Azure Key Vault przy użyciu poświadczeń dewelopera, zaloguj się do konta magazynu w programie Visual Studio lub zaloguj się przy użyciu Azure CLI. Jeśli jeszcze nie zainstalowano interfejsu wiersza polecenia platformy Azure, zobacz Jak zainstalować interfejs wiersza polecenia platformy Azure. Następujące polecenie można wykonać w panelu PowerShella dla deweloperów w programie Visual Studio lub w wierszu poleceń, gdy nie korzystasz z programu Visual Studio.
az login
Aby uzyskać więcej informacji, zobacz Logowanie do platformy Azure przy użyciu narzędzi deweloperskich.
Podczas tworzenia magazynu kluczy w portalu Entra lub Azure:
Skonfiguruj magazyn kluczy do używania kontroli dostępu opartej na rolach (RABC) platformy Azure. Jeśli nie korzystasz z usługi Azure Virtual Network, w tym na potrzeby lokalnego programowania i testowania, upewnij się, że dostęp publiczny w kroku Sieć jest włączony (zaznaczone). Włączenie dostępu publicznego uwidacznia tylko punkt końcowy magazynu kluczy. Uwierzytelnione konta są nadal wymagane do uzyskania dostępu.
Utwórz zarządzaną platformę Azure Identity (lub dodaj rolę do istniejącego Identity zarządzanego, którego zamierzasz użyć) z rolą użytkownika kryptograficznego usługi Key Vault . Przypisz Managed Identity do usługi Azure App Service, która hostuje wdrożenie: Ustawienia>Identity>Przypisane przez użytkownika>Dodaj.
Uwaga
Jeśli planujesz również lokalnie uruchomić aplikację z autoryzowanym użytkownikiem do dostępu do obiektów blob przy użyciu Azure CLI lub uwierzytelniania usługi platformy Azure programu Visual Studio, dodaj konto użytkownika platformy Azure dewelopera w obszarze Kontrola dostępu (IAM) z rolą Użytkownik Kryptograficzny Key Vault. Jeśli chcesz użyć Azure CLI za pośrednictwem programu Visual Studio, wykonaj polecenie
az login
z panelu Developer PowerShell i postępuj zgodnie z monitami, aby się uwierzytelnić w dzierżawie.Gdy szyfrowanie klucza jest aktywne, klucze w pliku klucza zawierają komentarz "This key is encrypted with Azure Key Vault." Po uruchomieniu aplikacji wybierz polecenie Wyświetl/edytuj z menu kontekstowego na końcu wiersza klucza, aby potwierdzić, że klucz jest obecny z zastosowanymi zabezpieczeniami magazynu kluczy.
Opcjonalnie można włączyć automatyczną rotację kluczy magazynu kluczy bez obaw o odszyfrowywanie ładunków przy użyciu kluczy ochrony danych na podstawie wygasłych/obróconych kluczy magazynu kluczy. Każdy wygenerowany klucz ochrony danych zawiera odwołanie do klucza magazynu kluczy używanego do jego zaszyfrowania. Upewnij się, że zachowasz klucze, które wygasły, nie usuwaj ich w Azure Key Vault. Ponadto należy użyć identyfikatora klucza bez wersji w konfiguracji magazynu kluczy aplikacji, gdzie identyfikator GUID klucza nie jest umieszczany na końcu identyfikatora (na przykład:
https://contoso.vault.azure.net/keys/data-protection
). Użyj podobnego okresu rotacji dla obu kluczy, przy czym klucz magazynu kluczy powinien obracać się częściej niż klucz ochrony danych, aby upewnić się, że nowy klucz magazynu kluczy jest używany w momencie rotacji klucza ochrony danych.
Ochrona kluczy za pomocą usługi Azure Key Vault implementuje funkcję IXmlEncryptor , która wyłącza ustawienia automatycznej ochrony danych, w tym lokalizację magazynu pierścienia kluczy. Aby skonfigurować dostawcę usługi Azure Blob Storage do przechowywania kluczy w magazynie obiektów blob, postępuj zgodnie z wytycznymi zawartymi w temacie Dostawcy magazynu kluczy w ASP.NET Core i wywołaj jedno z przeciążeń PersistKeysToAzureBlobStorage w aplikacji. W poniższym przykładzie użyto przeciążenia, które akceptuje URI dla obiektu blob i poświadczenie tokenu (TokenCredential), korzystając z Azure Managed Service Identity do kontroli dostępu na podstawie ról (RBAC).
Aby skonfigurować dostawcę usługi Azure Key Vault, wywołaj jedno z ProtectKeysWithAzureKeyVault przeciążeń. Poniższy przykład używa przeciążenia, które akceptuje identyfikator klucza i poświadczenie tokenu (TokenCredential), korzystając z funkcji Zarządzanej Identity na potrzeby kontroli dostępu opartej na rolach w środowisku produkcyjnym (ManagedIdentityCredential) lub w czasie rozwoju i testowania DefaultAzureCredential. Inne przeciążenia akceptują klienta magazynu kluczy lub identyfikator klienta aplikacji z kluczem tajnym klienta. Aby uzyskać więcej informacji, zobacz Dostawcy magazynu kluczy dla platformy ASP.NET Core.
Aby uzyskać więcej informacji na temat interfejsu API i uwierzytelniania zestawu Azure SDK, zobacz Uwierzytelnianie aplikacji platformy .NET w usługach platformy Azure przy użyciu biblioteki platformy Azure Identity i Zapewnianie dostępu do kluczy, certyfikatów i wpisów tajnych przy użyciu kontroli dostępu opartej na rolach platformy Azure. Aby uzyskać wskazówki dotyczące rejestrowania, zobacz Rejestrowanie przy użyciu zestawu Azure SDK dla platformy .NET: rejestrowanie bez rejestracji klienta. W przypadku aplikacji korzystających z wstrzykiwania zależności aplikacja może wywołać AddAzureClientsCore, przekazując true
dla enableLogForwarding
, w celu utworzenia i połączenia infrastruktury logowania.
W pliku, w Program
którym są zarejestrowane usługi:
TokenCredential? credential;
if (builder.Environment.IsProduction())
{
credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
// Local development and testing only
DefaultAzureCredentialOptions options = new()
{
// Specify the tenant ID to use the dev credentials when running the app locally
// in Visual Studio.
VisualStudioTenantId = "{TENANT ID}",
SharedTokenCacheTenantId = "{TENANT ID}"
};
credential = new DefaultAzureCredential(options);
}
services.AddDataProtection()
.SetApplicationName("{APPLICATION NAME}")
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);
{MANAGED IDENTITY CLIENT ID}
: identyfikator klienta zarządzanego Identity platformy Azure (GUID).
{TENANT ID}
: Identyfikator dzierżawcy.
{APPLICATION NAME}
: SetApplicationName ustawia unikatową nazwę tej aplikacji w systemie ochrony danych. Wartość powinna być zgodna z wdrożeniami aplikacji.
{BLOB URI}
: pełny identyfikator URI do pliku klucza. Identyfikator URI jest generowany przez usługę Azure Storage podczas tworzenia pliku klucza. Nie używaj SAS.
{KEY IDENTIFIER}
: identyfikator klucza usługi Azure Key Vault używany do szyfrowania kluczy. Zasady dostępu umożliwiają aplikacji dostęp do magazynu kluczy z uprawnieniami Get
, Unwrap Key
i Wrap Key
. Wersja klucza jest uzyskiwana po jego utworzeniu w portalu Entra lub Azure. Jeśli włączysz automatyczną rotację klucza magazynu kluczy, upewnij się, że używasz identyfikatora klucza bez wersji w konfiguracji magazynu kluczy aplikacji, czyli takiego, który nie zawiera na końcu identyfikatora GUID klucza (na przykład: https://contoso.vault.azure.net/keys/data-protection
).
Aby aplikacja komunikowała się i autoryzować się za pomocą usługi Azure Key Vault, Azure.Identity
pakiet NuGet musi być przywołyny przez aplikację.
Uwaga
Aby uzyskać wskazówki dotyczące dodawania pakietów do aplikacji .NET, zobacz artykuły w Instalowanie i zarządzanie pakietami oraz w proces korzystania z pakietów (dokumentacja NuGet). Sprawdź prawidłowe wersje pakietów pod adresem NuGet.org.
Uwaga
W środowiskach nieprodukcyjnych w poprzednim przykładzie użyto DefaultAzureCredential metody upraszczania uwierzytelniania podczas opracowywania aplikacji wdrażanych na platformie Azure przez połączenie poświadczeń używanych w środowiskach hostingu platformy Azure z poświadczeniami używanymi w środowisku lokalnym. Aby uzyskać więcej informacji, zobacz Uwierzytelnianie aplikacji platformy .NET hostowanych na platformie Azure do zasobów platformy Azure przy użyciu tożsamości zarządzanej przypisanej przez system.
Jeśli aplikacja używa starszych pakietów platformy Azure (Microsoft.AspNetCore.DataProtection.AzureStorage
i Microsoft.AspNetCore.DataProtection.AzureKeyVault
), zalecamy usunięcie tych odwołań i uaktualnienie do Azure.Extensions.AspNetCore.DataProtection.Blobs
pakietów i Azure.Extensions.AspNetCore.DataProtection.Keys
. Nowsze pakiety dotyczą kluczowych problemów z zabezpieczeniami i stabilnością.
Alternatywna metoda sygnatury dostępu współdzielonego (SAS): zamiast używać zarządzanego do dostępu do klucza obiektu blob w usłudze Azure Blob Storage, można wywołać przeciążenie Identity, które przyjmuje URI obiektu blob z tokenem SAS. Poniższy przykład nadal używa elementu (ManagedIdentityCredential produkcyjnego) lub (DefaultAzureCredential rozwojowego i testowania) dla elementu TokenCredential, jak pokazano w poprzednim przykładzie.
services.AddDataProtection()
.SetApplicationName("{APPLICATION NAME}")
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI WITH SAS}"))
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);
{APPLICATION NAME}
: SetApplicationName ustawia unikatową nazwę tej aplikacji w systemie ochrony danych. Wartość powinna być zgodna z wdrożeniami aplikacji.
{BLOB URI WITH SAS}
: Pełny identyfikator URI, w którym plik klucza powinien być przechowywany, wraz z tokenem SAS, jako parametr ciągu zapytania. Identyfikator URI jest generowany przez usługę Azure Storage w momencie, gdy żądasz sygnatury dostępu współdzielonego (SAS) dla przesłanego pliku klucza.
{KEY IDENTIFIER}
: identyfikator klucza usługi Azure Key Vault używany do szyfrowania kluczy. Zasady dostępu umożliwiają aplikacji dostęp do magazynu kluczy z uprawnieniami Get
, Unwrap Key
i Wrap Key
. Wersja klucza jest uzyskiwana po jego utworzeniu w portalu Entra lub Azure. Jeśli włączysz automatyczną rotację klucza magazynu kluczy, upewnij się, że używasz identyfikatora klucza bez wersji w konfiguracji magazynu kluczy aplikacji, czyli takiego, który nie zawiera na końcu identyfikatora GUID klucza (na przykład: https://contoso.vault.azure.net/keys/data-protection
).
Utrwalanie kluczy w systemie plików (PersistKeysToFileSystem
)
Aby przechowywać klucze w udziale UNC zamiast w domyślnej lokalizacji %LOCALAPPDATA% , skonfiguruj system za pomocą polecenia PersistKeysToFileSystem:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
}
Ostrzeżenie
Jeśli zmienisz lokalizację trwałości klucza, system nie będzie już automatycznie szyfrować kluczy magazynowanych, ponieważ nie wie, czy dpAPI jest odpowiednim mechanizmem szyfrowania.
Utrwalanie kluczy w bazie danych (PersistKeysToDbContext
)
Aby przechowywać klucze w bazie danych przy użyciu EntityFramework, skonfiguruj system za pomocą pakietu Microsoft.AspNetCore.DataProtection.EntityFrameworkCore :
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToDbContext<DbContext>()
}
Powyższy kod przechowuje klucze w skonfigurowanej bazie danych. Używany kontekst bazy danych musi implementować element IDataProtectionKeyContext
.
IDataProtectionKeyContext
uwidacznia właściwość DataProtectionKeys
public DbSet<DataProtectionKey> DataProtectionKeys { get; set; }
Ta właściwość reprezentuje tabelę, w której są przechowywane klucze. Utwórz tabelę ręcznie lub za pomocą DbContext
funkcji Migracje. Aby uzyskać więcej informacji, zobacz DataProtectionKey.
Interfejs API do konfiguracji ochrony kluczy (ProtectKeysWith\*
)
Można skonfigurować system, aby chronił klucze w spoczynku, wywołując dowolne z ProtectKeysWith\*
API konfiguracji. Rozważmy poniższy przykład, który przechowuje klucze w udziale UNC i szyfruje te klucze spoczywające przy użyciu określonego certyfikatu X.509.
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(Configuration["Thumbprint"]);
}
Możesz podać X509Certificate2 do ProtectKeysWithCertificate, taki jak certyfikat załadowany z pliku.
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", Configuration["Thumbprint"]));
}
Aby uzyskać więcej przykładów i dyskusji na temat wbudowanych mechanizmów szyfrowania kluczy, zobacz Szyfrowanie kluczy magazynowanych w systemach Windows i Azure przy użyciu platformy ASP.NET Core.
Usuń ochronę kluczy z dowolnym certyfikatem (UnprotectKeysWithAnyCertificate
)
Certyfikaty można wymieniać, a klucze odszyfrowywać w stanie spoczynku, używając tablicy certyfikatów X509Certificate2 z UnprotectKeysWithAnyCertificate.
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.ProtectKeysWithCertificate(
new X509Certificate2("certificate.pfx", Configuration["MyPasswordKey"));
.UnprotectKeysWithAnyCertificate(
new X509Certificate2("certificate_old_1.pfx", Configuration["MyPasswordKey_1"]),
new X509Certificate2("certificate_old_2.pfx", Configuration["MyPasswordKey_2"]));
}
Ustawianie domyślnego okresu istnienia klucza (SetDefaultKeyLifetime
)
Aby skonfigurować system do używania okresu istnienia klucza 14 dni zamiast domyślnego 90 dni, użyj polecenia SetDefaultKeyLifetime:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
}
Ustawianie nazwy aplikacji (SetApplicationName
)
Domyślnie system ochrony danych izoluje aplikacje od siebie na podstawie ścieżek głównych zawartości, nawet jeśli współużytkują to samo repozytorium kluczy fizycznych. Ta izolacja uniemożliwia aplikacjom zrozumienie chronionych ładunków innych aplikacji.
Aby udostępnić chronione ładunki między aplikacjami:
- W każdej aplikacji skonfiguruj SetApplicationName na tę samą wartość.
- Używaj tej samej wersji stosu Ochrony Danych API w aplikacjach. Wykonaj jedną z następujących czynności w plikach projektu aplikacji:
- Odwołuj się do tej samej wersji współdzielonego frameworku przez metapakiet Microsoft.AspNetCore.App.
- Odwołaj się do tej samej wersji pakietu Data Protection.
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.SetApplicationName("{APPLICATION NAME}");
}
SetApplicationName program wewnętrznie ustawia wartość DataProtectionOptions.ApplicationDiscriminator. Aby uzyskać więcej informacji na temat sposobu użycia klasyfikatora, zobacz poniższe sekcje w dalszej części tego artykułu:
Wyłączanie automatycznego generowania kluczy (DisableAutomaticKeyGeneration
)
Możesz mieć scenariusz, w którym nie chcesz, aby aplikacja automatycznie zamieniała klucze (tworzyła nowe klucze) w miarę zbliżania się do ich wygaśnięcia. Jednym z przykładów tego scenariusza mogą być aplikacje skonfigurowane w relacji podstawowej/pomocniczej, gdzie tylko podstawowa aplikacja jest odpowiedzialna za kluczowe problemy z zarządzaniem, a aplikacje pomocnicze mają po prostu widok pierścienia kluczy tylko do odczytu. Aplikacje pomocnicze można skonfigurować tak, aby traktować pierścień kluczy jako tylko do odczytu, konfigurując system przy użyciu polecenia DisableAutomaticKeyGeneration:
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.DisableAutomaticKeyGeneration();
}
Izolacja dla aplikacji
Gdy system ochrony danych jest dostarczany przez hosta ASP.NET Core, automatycznie izoluje aplikacje od siebie, nawet jeśli te aplikacje działają na tym samym koncie procesu roboczego i używają tego samego głównego materiału kluczowego. Jest to podobne do modyfikatora IsolateApps z elementu System.Web <machineKey>
.
Mechanizm izolacji działa, traktując każdą aplikację na komputerze lokalnym jako unikalną dzierżawę. W związku z tym IDataProtector dla danej aplikacji automatycznie uwzględnia identyfikator aplikacji jako wyróżnik (ApplicationDiscriminator). Unikatowy identyfikator aplikacji to ścieżka fizyczna aplikacji:
- W przypadku aplikacji hostowanych w usługach IIS unikatowy identyfikator to fizyczna ścieżka aplikacji w usługach IIS. Jeśli aplikacja jest wdrażana w środowisku farmy sieci Web, ta wartość jest stabilna przy założeniu, że środowiska usług IIS są podobnie skonfigurowane na wszystkich maszynach w farmie sieci Web.
- W przypadku aplikacji hostowanych samodzielnie na Kestrel serwerze unikatowy identyfikator to ścieżka fizyczna do aplikacji na dysku.
Unikatowy identyfikator jest przeznaczony do przetrwania resetowania — zarówno pojedynczej aplikacji, jak i samej maszyny.
Ten mechanizm izolacji zakłada, że aplikacje nie są złośliwe. Złośliwa aplikacja zawsze może mieć wpływ na dowolną inną aplikację działającą na tym samym koncie procesu roboczego. W udostępnionym środowisku hostingu, w którym aplikacje są wzajemnie niezaufane, dostawca hostingu powinien podjąć kroki w celu zapewnienia izolacji na poziomie systemu operacyjnego między aplikacjami, w tym oddzielenia bazowych repozytoriów kluczy aplikacji.
Jeśli system ochrony danych nie jest udostępniany przez hosta ASP.NET Core (na przykład, jeśli zostanie utworzony za pomocą konkretnego typu DataProtectionProvider
), izolacja aplikacji jest domyślnie wyłączona. Gdy izolacja aplikacji jest wyłączona, wszystkie aplikacje wspierane przez ten sam materiał kluczy mogą współdzielić ładunki, o ile zapewniają odpowiednie cele. Aby zapewnić izolację aplikacji w tym środowisku, wywołaj metodę SetApplicationName w obiekcie konfiguracji i podaj unikatową nazwę dla każdej aplikacji.
Ochrona danych i izolacja aplikacji
Rozważ następujące kwestie dotyczące izolacji aplikacji:
Gdy wiele aplikacji jest wskazywanych na to samo repozytorium kluczy, intencją jest to, że aplikacje współużytkują ten sam materiał klucza głównego. Ochrona danych jest opracowywana przy założeniu, że wszystkie aplikacje współużytkujące pierścień kluczy mogą uzyskiwać dostęp do wszystkich elementów w tym pierścieniu kluczy. Unikatowy identyfikator aplikacji służy do izolowania kluczy specyficznych dla aplikacji pochodzących z kluczy dostarczonych przez pierścień kluczy. Nie oczekuje uprawnień na poziomie elementu, takich jak te udostępniane przez usługę Azure KeyVault do wymuszania dodatkowej izolacji. Próba uzyskania uprawnień na poziomie elementu powoduje wygenerowanie błędów aplikacji. Jeśli nie chcesz polegać na wbudowanej izolacji aplikacji, należy używać oddzielnych lokalizacji magazynu kluczy i nie udostępniać ich między aplikacjami.
Dyskryminator aplikacji (ApplicationDiscriminator) jest używany, aby umożliwić różnym aplikacjom współużytkowanie tego samego materiału klucza głównego, ale zachowanie odrębnych ładunków kryptograficznych dla każdej z nich. Aby aplikacje mogły wzajemnie odczytywać swoje ładunki kryptograficzne, muszą mieć ten sam identyfikator aplikacji, więc należy wywołać
SetApplicationName
.W przypadku naruszenia zabezpieczeń aplikacji (na przykład przez atak RCE), wszystkie materiały klucza głównego dostępne dla tej aplikacji muszą być również uznawane za naruszone, niezależnie od stanu ochrony w spoczynku. Oznacza to, że jeśli dwie aplikacje wskazują na to samo repozytorium, nawet jeśli korzystają z odmiennych identyfikatorów aplikacji, kompromitacja jednej z nich jest funkcjonalnie równoważna z kompromitacją obu.
Ta klauzula "funkcjonalnie równoważna dla kompromisu obu" obowiązuje nawet wtedy, gdy obie aplikacje używają różnych mechanizmów ochrony kluczy w spoczynku. Zazwyczaj nie jest to oczekiwana konfiguracja. Mechanizm ochrony danych w spoczynku ma zapewnić ochronę w przypadku, gdy cyberatak uzyska dostęp do odczytu do repozytorium. Atakujący, który uzyskuje dostęp do zapisu w repozytorium (być może dlatego, że uzyskał uprawnienia do wykonania kodu w aplikacji), może wstawić złośliwe klucze do archiwum. System ochrony danych celowo nie zapewnia ochrony przed cyberatakiem, który uzyskuje możliwość zapisu w repozytorium kluczy.
Jeśli aplikacje muszą pozostać naprawdę odizolowane od siebie, powinny używać różnych repozytoriów kluczy. To naturalnie wypada z definicji "izolowanej". Aplikacje nie są izolowane, jeśli wszystkie mają dostęp do odczytu i zapisu nawzajem do swoich magazynów danych.
Zmienianie algorytmów za pomocą polecenia UseCryptographicAlgorithms
Stos ochrony danych umożliwia zmianę domyślnego algorytmu używanego przez nowo wygenerowane klucze. Najprostszym sposobem wykonania tej czynności jest wywołanie UseCryptographicAlgorithms z funkcji zwrotnej konfiguracji.
services.AddDataProtection()
.UseCryptographicAlgorithms(
new AuthenticatedEncryptorConfiguration()
{
EncryptionAlgorithm = EncryptionAlgorithm.AES_256_CBC,
ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
});
Domyślnym algorytmem szyfrowania jest AES-256-CBC, a domyślnym algorytmem walidacji jest HMACSHA256. Zasady domyślne mogą być ustawiane przez administratora systemu za pośrednictwem zasad dla całej maszyny, ale jawne wywołanie UseCryptographicAlgorithms
zastąpi domyślne zasady.
Wywołanie UseCryptographicAlgorithms
umożliwia określenie żądanego algorytmu ze wstępnie zdefiniowanej wbudowanej listy. Nie musisz martwić się o implementację algorytmu. W powyższym scenariuszu system ochrony danych próbuje użyć implementacji CNG AES, jeśli jest uruchomiona w systemie Windows. W przeciwnym razie wraca do klasy zarządzanej System.Security.Cryptography.Aes .
Implementację można określić ręcznie za pomocą wywołania metody UseCustomCryptographicAlgorithms.
Napiwek
Zmiana algorytmów nie ma wpływu na istniejące klucze w pierścieniu kluczy. Dotyczy tylko nowo wygenerowanych kluczy.
Określanie niestandardowych algorytmów zarządzanych
Aby określić niestandardowe algorytmy zarządzane, utwórz ManagedAuthenticatedEncryptorConfiguration wystąpienie wskazujące typy implementacji:
serviceCollection.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new ManagedAuthenticatedEncryptorConfiguration()
{
// A type that subclasses SymmetricAlgorithm
EncryptionAlgorithmType = typeof(Aes),
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// A type that subclasses KeyedHashAlgorithm
ValidationAlgorithmType = typeof(HMACSHA256)
});
Ogólnie rzecz biorąc, właściwości *Type muszą wskazywać na konkretne, możliwe do zainicjowania (poprzez publiczny konstruktor bez parametrów) implementacje SymmetricAlgorithm i KeyedHashAlgorithm, chociaż system obsługuje specjalne przypadki niektórych wartości, takich jak typeof(Aes)
, dla wygody.
Uwaga
SymmetricAlgorithm musi mieć długość klucza ≥ 128 bitów i rozmiar bloku ≥ 64 bitów i musi obsługiwać szyfrowanie w trybie CBC za pomocą dopełnienia PKCS #7. Algorytm KeyedHashAlgorithm musi mieć rozmiar skrótu równy lub większy niż 128 bitów i musi obsługiwać klucze o długości równej długości skrótu algorytmu. KeyedHashAlgorithm nie jest ściśle wymagany do bycia HMAC.
Określanie niestandardowych algorytmów CNG systemu Windows
Aby określić niestandardowy algorytm CNG systemu Windows przy użyciu szyfrowania w trybie CBC z walidacją HMAC, utwórz CngCbcAuthenticatedEncryptorConfiguration wystąpienie zawierające informacje algorytmiczne:
services.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new CngCbcAuthenticatedEncryptorConfiguration()
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256,
// Passed to BCryptOpenAlgorithmProvider
HashAlgorithm = "SHA256",
HashAlgorithmProvider = null
});
Uwaga
Algorytm szyfrowania bloków symetrycznych musi mieć długość >klucza = 128 bitów, rozmiar >bloku = 64 bity i musi obsługiwać szyfrowanie w trybie CBC za pomocą dopełnienia PKCS #7. Algorytm skrótu musi mieć rozmiar skrótu >= 128 bitów i musi umożliwiać otwieranie za pomocą flagi BCRYPT_ALG_HANDLE_HMAC_FLAG. *Właściwości dostawcy można ustawić na wartość null, aby użyć domyślnego dostawcy dla określonego algorytmu. Aby uzyskać więcej informacji, zobacz dokumentację BCryptOpenAlgorithmProvider .
Aby określić niestandardowy algorytm CNG systemu Windows przy użyciu szyfrowania w trybie Galois/Counter z walidacją, utwórz instancję CngGcmAuthenticatedEncryptorConfiguration zawierającą informacje o algorytmie:
services.AddDataProtection()
.UseCustomCryptographicAlgorithms(
new CngGcmAuthenticatedEncryptorConfiguration()
{
// Passed to BCryptOpenAlgorithmProvider
EncryptionAlgorithm = "AES",
EncryptionAlgorithmProvider = null,
// Specified in bits
EncryptionAlgorithmKeySize = 256
});
Uwaga
Algorytm szyfrowania bloków symetrycznych musi mieć długość >klucza = 128 bitów, rozmiar bloku o dokładnie 128 bitach i musi obsługiwać szyfrowanie GCM. Właściwość można ustawić na EncryptionAlgorithmProvider jako null, aby użyć domyślnego dostawcy dla danego algorytmu. Aby uzyskać więcej informacji, zobacz dokumentację BCryptOpenAlgorithmProvider .
Określanie innych algorytmów niestandardowych
Mimo że system ochrony danych nie jest uwidaczniony jako interfejs API pierwszej klasy, jest wystarczająco rozszerzalny, aby umożliwić określenie niemal dowolnego rodzaju algorytmu. ** Na przykład można zachować wszystkie klucze wewnątrz sprzętowego modułu zabezpieczeń (HSM) i zapewnić niestandardową implementację kluczowych procedur szyfrowania i deszyfrowania. Aby uzyskać więcej informacji, zobacz IAuthenticatedEncryptor w temacie Rozszerzalność kryptografii podstawowej.
Utrwalanie kluczy podczas hostowania w kontenerze platformy Docker
W przypadku hostowania w kontenerze Docker klucze powinny być przechowywane w jednym z następujących:
- Folder, który jest woluminem Dockera, przechowującym dane nawet po zakończeniu działania kontenera, na przykład jako wolumin udostępniony lub zamontowany na hoście.
- Dostawca zewnętrzny, taki jak Usługa Azure Blob Storage (pokazana w sekcji Ochrona kluczy za pomocą usługi Azure Key Vault (
ProtectKeysWithAzureKeyVault
) lub Redis.
Utrwalanie kluczy za pomocą usługi Redis
Do przechowywania kluczy powinny być używane tylko wersje usługi Redis obsługujące trwałość danych Redis. Usługa Azure Blob Storage jest trwała i może służyć do przechowywania kluczy. Aby uzyskać więcej informacji, zobacz ten problem w serwisie GitHub.
Przemysł drzewny
Włącz Information
lub niższy poziom rejestrowania, aby zdiagnozować problemy.
appsettings.json
Poniższy plik umożliwia rejestrowanie danych za pomocą interfejsu API ochrony danych.
{
"Logging": {
"LogLevel": {
"Microsoft.AspNetCore.DataProtection": "Information"
}
}
}
Aby uzyskać więcej informacji na temat rejestrowania, zobacz Rejestrowanie na platformie .NET Core i ASP.NET Core.