Condividi tramite


Procedure consigliate per la distribuzione delle password e di altri dati sensibili in ASP.NET e in Servizio app di Azure

di Rick Anderson

Questa esercitazione illustra come il codice può archiviare e accedere in modo sicuro alle informazioni sicure. Il punto più importante è che non è mai consigliabile archiviare password o altri dati sensibili nel codice sorgente e non usare segreti di produzione in modalità di sviluppo e test.

Il codice di esempio è una semplice app console del processo Web e un'app MVC ASP.NET che deve accedere a un database stringa di connessione password, Twilio, Google e SendGrid proteggere le chiavi.

Sono indicate anche le impostazioni locali e PHP.

Uso delle password nell'ambiente di sviluppo

Le esercitazioni mostrano spesso dati sensibili nel codice sorgente, con un'avvertenza che non è mai consigliabile archiviare dati sensibili nel codice sorgente. Ad esempio, l'app ASP.NET MVC 5 con SMS e posta elettronica 2FA mostra quanto segue nel file 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>

Il file web.config è il codice sorgente, quindi questi segreti non devono mai essere archiviati in tale file. Fortunatamente, l'elemento <appSettings> ha un file attributo che consente di specificare un file esterno che contiene impostazioni di configurazione dell'app sensibili. È possibile spostare tutti i segreti in un file esterno, purché il file esterno non venga archiviato nell'albero di origine. Nel markup seguente, ad esempio, il file AppSettingsSecrets.config contiene tutti i segreti dell'app:

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

Il markup nel file esterno (AppSettingsSecrets.config in questo esempio) è lo stesso markup presente nel file 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>

Il runtime ASP.NET unisce il contenuto del file esterno con il markup nell'elemento <appSettings> . Il runtime ignora l'attributo del file, se non è possibile trovare il file specificato.

Avviso

Sicurezza: non aggiungere il file con estensione config dei segreti al progetto o archiviarlo nel controllo del codice sorgente. Per impostazione predefinita, Visual Studio imposta su Build Action Content, il che significa che il file viene distribuito. Per altre informazioni, vedere Perché non vengono distribuiti tutti i file nella cartella del progetto? Sebbene sia possibile usare qualsiasi estensione per il file con estensione config dei segreti, è consigliabile mantenerla con estensione config, perché i file di configurazione non vengono gestiti da IIS. Si noti anche che il file AppSettingsSecrets.config è costituito da due livelli di directory fino al file web.config , quindi è completamente fuori dalla directory della soluzione. Spostando il file dalla directory della soluzione, "git add *" non lo aggiungerà al repository.

Uso di stringa di connessione nell'ambiente di sviluppo

Visual Studio crea nuovi progetti ASP.NET che usano LocalDB. LocalDB è stato creato in modo specifico per l'ambiente di sviluppo. Non richiede una password, pertanto non è necessario eseguire alcuna operazione per impedire che i segreti vengano controllati nel codice sorgente. Alcuni team di sviluppo usano le versioni complete di SQL Server (o altri DBMS) che richiedono una password.

È possibile usare l'attributo configSource per sostituire l'intero <connectionStrings> markup. A differenza dell'attributo <appSettings> file che unisce il markup, l'attributo configSource sostituisce il markup. Il markup seguente illustra l'attributo configSource nel file web.config :

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

Nota

Se si usa l'attributo configSource come illustrato in precedenza per spostare i stringa di connessione in un file esterno e si dispone di Visual Studio per creare un nuovo sito Web, non sarà in grado di rilevare l'uso di un database e non si otterrà la possibilità di configurare il database quando si esegue la pubblicazione in Azure da Visual Studio. Se si usa l'attributo configSource , è possibile usare PowerShell per creare e distribuire il sito Web e il database oppure creare il sito Web e il database nel portale prima della pubblicazione.

Avviso

Sicurezza: a differenza del file AppSettingsSecrets.config, il file stringa di connessione s esterno deve trovarsi nella stessa directory del file web.config radice, quindi è necessario adottare precauzioni per assicurarsi di non archiviarlo nel repository di origine.

Nota

Avviso di sicurezza nel file dei segreti: è consigliabile non usare segreti di produzione in fase di test e sviluppo. L'uso di password di produzione in test o sviluppo perde tali segreti.

App console di Processi Web

Il file app.config usato da un'app console non supporta i percorsi relativi, ma supporta i percorsi assoluti. È possibile usare un percorso assoluto per spostare i segreti dalla directory del progetto. Il markup seguente mostra i segreti nel file C:\secrets\AppSettingsSecrets.config e dati non sensibili nel file 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>

Distribuzione di segreti in Azure

Quando si distribuisce l'app Web in Azure, il file AppSettingsSecrets.config non verrà distribuito ,ovvero ciò che si vuole. A tale scopo, è possibile passare al portale di gestione di Azure e impostarli manualmente:

  1. Passare a https://portal.azure.come accedere con le credenziali di Azure.
  2. Fare clic su Sfoglia > App Web, quindi sul nome dell'app Web.
  3. Fare clic su Tutte le impostazioni >Impostazioni applicazione.

Le impostazioni dell'app e i valori stringa di connessione sostituiscono le stesse impostazioni nel file web.config. In questo esempio queste impostazioni non sono state distribuite in Azure, ma se queste chiavi si trovavano nel file web.config , le impostazioni visualizzate nel portale avranno la precedenza.

Una procedura consigliata consiste nel seguire un flusso di lavoro DevOps e usare Azure PowerShell (o un altro framework, ad esempio Chef o Puppet) per automatizzare l'impostazione di questi valori in Azure. Lo script di PowerShell seguente usa Export-CliXml per esportare i segreti crittografati su disco:

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

Nello script precedente "Name" è il nome della chiave privata, ad esempio ""FB_AppSecret" o "TwitterSecret". È possibile visualizzare il file ".credential" creato dallo script nel browser. Il frammento di codice seguente testa ognuno dei file di credenziali e imposta i segreti per l'app Web denominata:

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

Avviso

Sicurezza: non includere password o altri segreti nello script di PowerShell, in modo da sconfiggere lo scopo di usare uno script di PowerShell per distribuire dati sensibili. Il cmdlet Get-Credential fornisce un meccanismo sicuro per ottenere una password. L'uso di un prompt dell'interfaccia utente può impedire la perdita di una password.

Distribuzione di stringa di connessione di database

Le stringa di connessione di database vengono gestite in modo analogo alle impostazioni dell'app. Se si distribuisce l'app Web da Visual Studio, il stringa di connessione verrà configurato automaticamente. È possibile verificarlo nel portale. Il modo consigliato per impostare il stringa di connessione è con PowerShell.

Note per PHP

Poiché le coppie chiave-valore per le impostazioni dell'app e le stringa di connessione vengono archiviate nelle variabili di ambiente nel servizio app Azure, gli sviluppatori che usano qualsiasi framework di app Web (ad esempio PHP) possono facilmente recuperare questi valori. Vedere il post di blog sul funzionamento delle stringhe di connessione e delle stringhe di connessione di Stefan Schackow di Stefan Schackow per leggere le impostazioni dell'app e le stringa di connessione.

Note per i server locali

Se si esegue la distribuzione in server Web locali, è possibile proteggere i segreti crittografando le sezioni di configurazione dei file di configurazione. In alternativa, è possibile usare lo stesso approccio consigliato per Siti Web di Azure: mantenere le impostazioni di sviluppo nei file di configurazione e usare i valori delle variabili di ambiente per le impostazioni di produzione. In questo caso, tuttavia, è necessario scrivere il codice dell'applicazione per le funzionalità automatiche nei siti Web di Azure: recuperare le impostazioni dalle variabili di ambiente e usare tali valori al posto delle impostazioni del file di configurazione oppure usare le impostazioni del file di configurazione quando le variabili di ambiente non vengono trovate.

Risorse aggiuntive

Vedere Siti Web di Windows Azure di Stefan Schackow: Funzionamento delle stringhe di applicazione e delle stringhe di connessione

Grazie speciale a Barry Dorrans ( @blowdart ) e Carlos Farre per la revisione.