Bewährte Methoden für die Bereitstellung von Kennwörtern und anderen sensiblen Daten für ASP.NET und Azure App Service

von Rick Anderson

In diesem Tutorial wird gezeigt, wie Ihr Code sichere Informationen speichern und darauf zugreifen kann. Der wichtigste Punkt ist, dass Sie niemals Kennwörter oder andere vertrauliche Daten im Quellcode speichern sollten, und Sie sollten keine Produktionsgeheimnisse im Entwicklungs- und Testmodus verwenden.

Der Beispielcode ist eine einfache WebJob-Konsolen-App und eine ASP.NET MVC-App, die Zugriff auf eine Datenbank benötigt, Verbindungszeichenfolge Kennwort, Twilio, Google und SendGrid sichere Schlüssel.

Lokale Einstellungen und PHP werden ebenfalls erwähnt.

Arbeiten mit Kennwörtern in der Entwicklungsumgebung

Tutorials zeigen häufig vertrauliche Daten im Quellcode an, hoffentlich mit einer Einschränkung, dass Sie vertrauliche Daten niemals im Quellcode speichern sollten. In meinem Tutorial ASP.NET MVC 5-App mit SMS und E-Mail 2FA wird beispielsweise Folgendes in der web.config-Datei gezeigt:

</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>

Die web.config-Datei ist Quellcode, sodass diese Geheimnisse niemals in dieser Datei gespeichert werden sollten. Glücklicherweise verfügt das <appSettings> Element über ein file Attribut, mit dem Sie eine externe Datei angeben können, die einstellungen für vertrauliche App-Konfigurationen enthält. Sie können alle Ihre Geheimnisse in eine externe Datei verschieben, solange die externe Datei nicht in Ihre Quellstruktur eingecheckt ist. Im folgenden Markup enthält die Datei beispielsweiseAppSettingsSecrets.config alle App-Geheimnisse:

</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>

Das Markup in der externen Datei (AppSettingsSecrets.config in diesem Beispiel) ist das gleiche Markup in der web.config-Datei :

<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>

Die ASP.NET Runtime führt den Inhalt der externen Datei mit dem Markup im <appSettings-Element> zusammen. Falls die angegebene Datei nicht gefunden wird, wird das Dateiattribut ignoriert.

Warnung

Sicherheit: Fügen Sie Ihre Geheimnisse nicht .config Datei zu Ihrem Projekt hinzu, oder überprüfen Sie sie nicht in die Quellcodeverwaltung. Standardmäßig legt Visual Studio den Build Action auf fest Content, was bedeutet, dass die Datei bereitgestellt wird. Weitere Informationen finden Sie unter Warum werden nicht alle Dateien in meinem Projektordner bereitgestellt? Obwohl Sie eine beliebige Erweiterung für die Geheimnisse .config-Datei verwenden können, empfiehlt es sich, sie .configbeizubehalten, da Konfigurationsdateien nicht von IIS bereitgestellt werden. Beachten Sie auch, dass die AppSettingsSecrets.config-Datei zwei Verzeichnisebenen von der web.config Datei entfernt ist, sodass sie sich vollständig aus dem Lösungsverzeichnis befindet. Wenn Sie die Datei aus dem Projektmappenverzeichnis verschieben, wird sie von "git add *" nicht zu Ihrem Repository hinzugefügt.

Arbeiten mit Verbindungszeichenfolgen in der Entwicklungsumgebung

Visual Studio erstellt neue ASP.NET-Projekte, die LocalDB verwenden. LocalDB wurde speziell für die Entwicklungsumgebung erstellt. Es ist kein Kennwort erforderlich, daher müssen Sie nichts tun, um zu verhindern, dass Geheimnisse in Ihren Quellcode eingecheckt werden. Einige Entwicklungsteams verwenden die Vollversionen von SQL Server (oder anderen DBMS), für die ein Kennwort erforderlich ist.

Sie können das configSource -Attribut verwenden, um das gesamte <connectionStrings> Markup zu ersetzen. <appSettings>file Im Gegensatz zum Attribut, das das Markup zusammenführt, ersetzt das configSource Attribut das Markup. Das folgende Markup zeigt das configSource Attribut in der web.config-Datei :

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

Hinweis

Wenn Sie das configSource -Attribut wie oben gezeigt verwenden, um Ihre Verbindungszeichenfolgen in eine externe Datei zu verschieben, und Visual Studio eine neue Website erstellt, kann es nicht erkennen, dass Sie eine Datenbank verwenden, und Sie haben keine Möglichkeit, die Datenbank zu konfigurieren, wenn Sie über Visual Studio in Azure veröffentlichen. Wenn Sie das configSource Attribut verwenden, können Sie PowerShell verwenden, um Ihre Website und Datenbank zu erstellen und bereitzustellen, oder Sie können die Website und die Datenbank im Portal erstellen, bevor Sie veröffentlichen.

Warnung

Sicherheit: Im Gegensatz zur AppSettingsSecrets.config-Datei muss sich die externe Verbindungszeichenfolgendatei im selben Verzeichnis wie die Stammdateiweb.config befinden. Daher müssen Sie Vorkehrungen treffen, um sicherzustellen, dass Sie sie nicht in Ihr Quellrepository einchecken.

Hinweis

Sicherheitswarnung für Geheimnisdatei: Eine bewährte Methode besteht darin, keine Produktionsgeheimnisse in Test und Entwicklung zu verwenden. Durch die Verwendung von Produktionskennwörtern im Test oder in der Entwicklung werden diese Geheimnisse geleakt.

WebJobs-Konsolen-Apps

Die app.config-Datei , die von einer Konsolen-App verwendet wird, unterstützt keine relativen Pfade, aber absolute Pfade. Sie können einen absoluten Pfad verwenden, um Ihre Geheimnisse aus Ihrem Projektverzeichnis zu verschieben. Das folgende Markup zeigt die Geheimnisse in der C:\secrets\AppSettingsSecrets.config-Datei und nicht vertrauliche Daten in der app.config-Datei .

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

Bereitstellen von Geheimnissen in Azure

Wenn Sie Ihre Web-App in Azure bereitstellen, wird die AppSettingsSecrets.config-Datei nicht bereitgestellt (was Sie möchten). Sie können zum Azure-Verwaltungsportal wechseln und sie manuell festlegen, um folgendes zu tun:

  1. Wechseln Sie zu https://portal.azure.com, und melden Sie sich mit Ihren Azure-Anmeldeinformationen an.
  2. Klicken Sie auf Web-Apps durchsuchen>, und klicken Sie dann auf den Namen Ihrer Web-App.
  3. Klicken Sie auf Alle Einstellungen > Anwendungseinstellungen.

Die App-Einstellungen und Verbindungszeichenfolge-Werte überschreiben dieselben Einstellungen in der web.config-Datei. In unserem Beispiel haben wir diese Einstellungen nicht in Azure bereitgestellt, aber wenn sich diese Schlüssel in der web.config-Datei befinden, haben die im Portal angezeigten Einstellungen Vorrang.

Eine bewährte Methode besteht darin, einen DevOps-Workflow zu befolgen und Azure PowerShell (oder ein anderes Framework wie Chef oder Puppet) zu verwenden, um das Festlegen dieser Werte in Azure zu automatisieren. Das folgende PowerShell-Skript verwendet Export-CliXml , um die verschlüsselten Geheimnisse auf den Datenträger zu exportieren:

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

Im obigen Skript ist "Name" der Name des geheimen Schlüssels, z. B. "FB_AppSecret" oder "TwitterSecret". Sie können die vom Skript erstellte Datei ".credential" in Ihrem Browser anzeigen. Der folgende Codeausschnitt testet jede der Anmeldeinformationsdateien und legt die Geheimnisse für die benannte Web-App fest:

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

Warnung

Sicherheit: Schließen Sie keine Kennwörter oder andere Geheimnisse in das PowerShell-Skript ein. Dadurch wird der Zweck der Verwendung eines PowerShell-Skripts zum Bereitstellen vertraulicher Daten umgangen. Das Cmdlet Get-Credential bietet einen sicheren Mechanismus zum Abrufen eines Kennworts. Die Verwendung einer Benutzeroberflächenaufforderung kann das Unentkennen eines Kennworts verhindern.

Bereitstellen von DB-Verbindungszeichenfolgen

DB-Verbindungszeichenfolgen werden ähnlich wie App-Einstellungen behandelt. Wenn Sie Ihre Web-App über Visual Studio bereitstellen, wird die Verbindungszeichenfolge für Sie konfiguriert. Sie können dies im Portal überprüfen. Die empfohlene Möglichkeit zum Festlegen der Verbindungszeichenfolge ist PowerShell.

Hinweise für PHP

Da die Schlüssel-Wert-Paare sowohl für App-Einstellungen als auch für Verbindungszeichenfolgen in Umgebungsvariablen auf Azure App Service gespeichert sind, können Entwickler, die beliebige Web-App-Frameworks (z. B. PHP) verwenden, diese Werte problemlos abrufen. Lesen Sie den Blogbeitrag Windows Azure-Websites von Stefan Schackow: How Application Strings and Connection Strings Work(How Application Strings and Connection Strings Work ), in dem ein PHP-Codeausschnitt zum Lesen von App-Einstellungen und Verbindungszeichenfolgen angezeigt wird.

Hinweise für lokale Server

Wenn Sie die Bereitstellung auf lokalen Webservern durchführen, können Sie geheimnisse schützen, indem Sie die Konfigurationsabschnitte der Konfigurationsdateien verschlüsseln. Alternativ können Sie denselben Ansatz verwenden, der für Azure-Websites empfohlen wird: Behalten Sie Entwicklungseinstellungen in Konfigurationsdateien bei, und verwenden Sie Umgebungsvariablenwerte für Produktionseinstellungen. In diesem Fall müssen Sie jedoch Anwendungscode für funktionen schreiben, die in Azure Websites automatisch sind: Abrufen von Einstellungen aus Umgebungsvariablen und Verwenden dieser Werte anstelle von Konfigurationsdateieinstellungen oder Verwenden von Konfigurationsdateieinstellungen, wenn Umgebungsvariablen nicht gefunden werden.

Weitere Ressourcen

Siehe Stefan Schackows Windows Azure-Websites: Funktionsweise von Anwendungszeichenfolgen und Verbindungszeichenfolgen

Besonderer Dank geht an Barry Dorrans ( @blowdart ) und Carlos Farre für die Bewertung.