Udostępnij za pośrednictwem


Najlepsze rozwiązania dotyczące wdrażania haseł i innych danych poufnych na platformie ASP.NET i w usłudze Azure App Service

Autor: Rick Anderson

W tym samouczku pokazano, jak kod może bezpiecznie przechowywać i uzyskiwać dostęp do bezpiecznych informacji. Najważniejszym punktem jest to, że nigdy nie należy przechowywać haseł ani innych poufnych danych w kodzie źródłowym i nie należy używać wpisów tajnych produkcyjnych w trybie programowania i testowania.

Przykładowy kod to prosta aplikacja konsolowa zadania WebJob i aplikacja ASP.NET MVC, która wymaga dostępu do bazy danych parametry połączenia hasła, Twilio, Google i SendGrid bezpiecznych kluczy.

Wspomniano również o ustawieniach lokalnych i php.

Praca z hasłami w środowisku projektowym

Samouczki często pokazują poufne dane w kodzie źródłowym, miejmy nadzieję, że nie należy przechowywać poufnych danych w kodzie źródłowym. Na przykład mój samouczek ASP.NET MVC 5 z wiadomością SMS i pocztą e-mail 2FA przedstawia następujące informacje w pliku web.config :

</connectionStrings>
   <appSettings>
      <add key="webpages:Version" value="3.0.0.0" />
      <!-- Markup removed for clarity. -->
      
      <!-- SendGrid-->
      <add key="mailAccount" value="account" />
      <add key="mailPassword" value="my password" />
      <!-- Twilio-->
      <add key="TwilioSid" value="My SID" />
      <add key="TwilioToken" value="My Token" />
      <add key="TwilioFromPhone" value="+12065551234" />

      <add key="GoogClientID" value="1234.apps.googleusercontent.com" />
      <add key="GoogClientSecret" value="My GCS" />
   </appSettings>
 <system.web>

Plik web.config jest kodem źródłowym, więc te wpisy tajne nigdy nie powinny być przechowywane w tym pliku. <appSettings> Na szczęście element ma file atrybut, który umożliwia określenie pliku zewnętrznego zawierającego poufne ustawienia konfiguracji aplikacji. Wszystkie wpisy tajne można przenieść do pliku zewnętrznego, o ile plik zewnętrzny nie jest zaewidencjonowany w drzewie źródłowym. Na przykład w poniższym znaczniku plik AppSettingsSecrets.config zawiera wszystkie wpisy tajne aplikacji:

</connectionStrings>
   <appSettings file="..\..\AppSettingsSecrets.config">      
      <add key="webpages:Version" value="3.0.0.0" />
      <add key="webpages:Enabled" value="false" />
      <add key="ClientValidationEnabled" value="true" />
      <add key="UnobtrusiveJavaScriptEnabled" value="true" />      
   </appSettings>
  <system.web>

Znaczniki w pliku zewnętrznym (AppSettingsSecrets.config w tym przykładzie) są tymi samymi znacznikami znajdującymi się w pliku web.config :

<appSettings>   
   <!-- SendGrid-->
   <add key="mailAccount" value="My mail account." />
   <add key="mailPassword" value="My mail password." />
   <!-- Twilio-->
   <add key="TwilioSid" value="My Twilio SID." />
   <add key="TwilioToken" value="My Twilio Token." />
   <add key="TwilioFromPhone" value="+12065551234" />

   <add key="GoogClientID" value="1.apps.googleusercontent.com" />
   <add key="GoogClientSecret" value="My Google client secret." />
</appSettings>

Środowisko uruchomieniowe ASP.NET scala zawartość pliku zewnętrznego z znacznikami w <elemecie appSettings> . Środowisko uruchomieniowe ignoruje atrybut pliku, jeśli nie można odnaleźć określonego pliku.

Ostrzeżenie

Zabezpieczenia — nie należy dodawać wpisów tajnych .config pliku do projektu ani sprawdzać go w kontroli źródła. Domyślnie program Visual Studio ustawia wartość Build ActionContentna , co oznacza, że plik jest wdrażany. Aby uzyskać więcej informacji, zobacz Dlaczego nie wszystkie pliki w folderze projektu są wdrażane? Chociaż można użyć dowolnego rozszerzenia dla pliku .configwpisów tajnych , najlepiej zachować je .config, ponieważ pliki konfiguracji nie są obsługiwane przez usługi IIS. Zwróć również uwagę, że plik AppSettingsSecrets.config jest dwoma poziomami katalogów w górę z pliku web.config , więc jest całkowicie poza katalogem rozwiązania. Przeniesienie pliku z katalogu rozwiązania "git add *" nie spowoduje dodania go do repozytorium.

Praca z parametrami połączenia w środowisku projektowym

Program Visual Studio tworzy nowe projekty ASP.NET korzystające z bazy danych LocalDB. Baza danych LocalDB została utworzona specjalnie dla środowiska deweloperskiego. Nie wymaga hasła, dlatego nie trzeba nic robić, aby zapobiec ewidencjowaniu wpisów tajnych w kodzie źródłowym. Niektóre zespoły programistyczne używają pełnych wersji SQL Server (lub innych dbMS), które wymagają hasła.

Możesz użyć atrybutu configSource , aby zastąpić cały <connectionStrings> znacznik. W przeciwieństwie do atrybutu <appSettings>file , który scala znaczniki, configSource atrybut zastępuje znaczniki. Na poniższej configSource adiustacji jest wyświetlany atrybut w pliku web.config :

<connectionStrings configSource="ConnectionStrings.config">
</connectionStrings>

Uwaga

Jeśli używasz atrybutu configSource , jak pokazano powyżej, aby przenieść parametry połączenia do pliku zewnętrznego i program Visual Studio utworzy nową witrynę sieci Web, nie będzie w stanie wykryć, że używasz bazy danych i nie będzie można skonfigurować bazy danych podczas publikowania na platformie Azure z programu Visual Studio. Jeśli używasz atrybutu configSource , możesz użyć programu PowerShell do utworzenia i wdrożenia witryny internetowej i bazy danych albo utworzyć witrynę internetową i bazę danych w portalu przed opublikowaniem.

Ostrzeżenie

Zabezpieczenia — w przeciwieństwie do pliku AppSettingsSecrets.config plik parametrów połączenia zewnętrznego musi znajdować się w tym samym katalogu co plik głównyweb.config , więc należy podjąć środki ostrożności, aby upewnić się, że nie zaewidencjonujesz go w repozytorium źródłowym.

Uwaga

Ostrzeżenie o zabezpieczeniach w pliku wpisów tajnych: Najlepszym rozwiązaniem jest nie używanie wpisów tajnych produkcyjnych podczas testowania i programowania. Używanie haseł produkcyjnych w środowisku testowym lub programistycznym wycieka tych wpisów tajnych.

Aplikacje konsolowe zadań WebJob

Plik app.config używany przez aplikację konsolową nie obsługuje ścieżek względnych, ale obsługuje ścieżki bezwzględne. Możesz użyć ścieżki bezwzględnej, aby przenieść wpisy tajne z katalogu projektu. Poniższy znacznik pokazuje wpisy tajne w pliku C:\secrets\AppSettingsSecrets.config i dane niewrażliwe w pliku app.config .

<configuration>
  <appSettings file="C:\secrets\AppSettingsSecrets.config">
    <add key="TwitterMaxThreads" value="24" />
    <add key="StackOverflowMaxThreads" value="24" />
    <add key="MaxDaysForPurge" value="30" />
  </appSettings>
</configuration>

Wdrażanie wpisów tajnych na platformie Azure

Podczas wdrażania aplikacji internetowej na platformie Azure plik AppSettingsSecrets.config nie zostanie wdrożony (to właśnie chcesz). Możesz przejść do portalu zarządzania Azure i ustawić je ręcznie, aby to zrobić:

  1. Przejdź do https://portal.azure.comwitryny i zaloguj się przy użyciu poświadczeń platformy Azure.
  2. Kliknij pozycję Przeglądaj > Web Apps, a następnie kliknij nazwę aplikacji internetowej.
  3. Kliknij pozycję Wszystkie ustawienia Ustawienia > aplikacji.

Ustawienia aplikacjii parametry połączenia wartości zastępują te same ustawienia w pliku web.config. W naszym przykładzie nie wdrożyliśmy tych ustawień na platformie Azure, ale jeśli te klucze znajdowały się w pliku web.config , ustawienia wyświetlane w portalu miałyby pierwszeństwo.

Najlepszym rozwiązaniem jest użycie przepływu pracy metodyki DevOps i użycie Azure PowerShell (lub innej platformy, takiej jak Chef lub Puppet), aby zautomatyzować ustawianie tych wartości na platformie Azure. Następujący skrypt programu PowerShell używa polecenia Export-CliXml do eksportowania zaszyfrowanych wpisów tajnych na dysku:

param(
  [Parameter(Mandatory=$true)] 
  [String]$Name,
  [Parameter(Mandatory=$true)]
  [String]$Password)

$credPath = $PSScriptRoot + '\' + $Name + ".credential"
$PWord = ConvertTo-SecureString –String $Password –AsPlainText -Force 
$Credential = New-Object –TypeName `
System.Management.Automation.PSCredential –ArgumentList $Name, $PWord
$Credential | Export-CliXml $credPath

W powyższym skrypcie "Name" jest nazwą klucza tajnego, takiego jak "FB_AppSecret" lub "TwitterSecret". Plik ".credential" utworzony przez skrypt można wyświetlić w przeglądarce. Poniższy fragment kodu sprawdza każdy z plików poświadczeń i ustawia wpisy tajne dla nazwanej aplikacji internetowej:

Function GetPW_fromCredFile { Param( [String]$CredFile )
  $Credential = GetCredsFromFile $CredFile
  $PW = $Credential.GetNetworkCredential().Password  
  # $user just for debugging.
  $user = $Credential.GetNetworkCredential().username 
  Return $PW
}	
$AppSettings = @{	
  "FB_AppSecret"     = GetPW_fromCredFile "FB_AppSecret.credential";
  "GoogClientSecret" = GetPW_fromCredFile "GoogClientSecret.credential";
  "TwitterSecret"    = GetPW_fromCredFile "TwitterSecret.credential";
}
Set-AzureWebsite -Name $WebSiteName -AppSettings $AppSettings

Ostrzeżenie

Zabezpieczenia — nie dołączaj haseł ani innych wpisów tajnych w skrypcie programu PowerShell, co powoduje porażkę w celu wdrożenia poufnych danych za pomocą skryptu programu PowerShell. Polecenie cmdlet Get-Credential zapewnia bezpieczny mechanizm uzyskiwania hasła. Użycie monitu interfejsu użytkownika może zapobiec wyciekowi hasła.

Wdrażanie parametrów połączenia bazy danych

Parametry połączenia bazy danych są obsługiwane podobnie do ustawień aplikacji. Jeśli wdrożysz aplikację internetową z poziomu programu Visual Studio, parametry połączenia zostanie skonfigurowana dla Ciebie. Możesz to sprawdzić w portalu. Zalecanym sposobem ustawienia parametry połączenia jest program PowerShell.

Uwagi dotyczące języka PHP

Ponieważ pary klucz-wartość zarówno dla ustawień aplikacji, jak i parametrów połączenia są przechowywane w zmiennych środowiskowych na Azure App Service, deweloperzy korzystający z dowolnych struktur aplikacji internetowych (takich jak PHP) mogą łatwo pobrać te wartości. Zobacz wpis w blogu w blogu Dotyczącym parametrów aplikacji i parametrów połączenia w witrynach internetowych platformy Windows Schackow w języku Php, w którym przedstawiono fragment kodu PHP służący do odczytywania ustawień aplikacji i parametrów połączenia.

Uwagi dotyczące serwerów lokalnych

Jeśli wdrażasz na lokalnych serwerach sieci Web, możesz pomóc zabezpieczyć wpisy tajne, szyfrując sekcje konfiguracji plików konfiguracji. Alternatywnie możesz użyć tego samego podejścia zalecanego dla usługi Azure Websites: zachować ustawienia programistyczne w plikach konfiguracji i użyć wartości zmiennych środowiskowych dla ustawień produkcyjnych. W takim przypadku należy jednak napisać kod aplikacji dla funkcji automatycznych w usłudze Azure Websites: pobierać ustawienia ze zmiennych środowiskowych i używać tych wartości zamiast ustawień pliku konfiguracji lub używać ustawień pliku konfiguracji, gdy zmienne środowiskowe nie zostaną znalezione.

Dodatkowe zasoby

Zobacz Witryny sieci Web platformy Windows Azure w programie Stefan Schackow: Jak działają parametry aplikacji i parametry połączenia

Specjalne podziękowania barry Dorrans ( @blowdart ) i Carlos Farre do przeglądu.