Melhores práticas para implantar senhas e outros dados confidenciais no ASP.NET e no Serviço de Aplicativo do Azure

por Rick Anderson

Este tutorial mostra como seu código pode armazenar e acessar informações seguras com segurança. O ponto mais importante é que você nunca deve armazenar senhas ou outros dados confidenciais no código-fonte e não deve usar segredos de produção no modo de desenvolvimento e teste.

O código de exemplo é um aplicativo de console WebJob simples e um aplicativo MVC ASP.NET que precisa de acesso a um banco de dados cadeia de conexão senha, chaves seguras Twilio, Google e SendGrid.

As configurações locais e o PHP também são mencionados.

Trabalhando com senhas no ambiente de desenvolvimento

Os tutoriais frequentemente mostram dados confidenciais no código-fonte, com uma ressalva de que você nunca deve armazenar dados confidenciais no código-fonte. Por exemplo, meu aplicativo MVC 5 ASP.NET com SMS e email 2FA mostra o seguinte no arquivo 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>

O arquivoweb.config é o código-fonte, portanto, esses segredos nunca devem ser armazenados nesse arquivo. Felizmente, o <appSettings> elemento tem um file atributo que permite especificar um arquivo externo que contém configurações confidenciais do aplicativo. Você pode mover todos os seus segredos para um arquivo externo, desde que o arquivo externo não seja verificado em sua árvore de origem. Por exemplo, na marcação a seguir, o arquivo AppSettingsSecrets.config contém todos os segredos do aplicativo:

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

A marcação no arquivo externo (AppSettingsSecrets.config neste exemplo) é a mesma marcação encontrada no arquivo 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>

O runtime ASP.NET mescla o conteúdo do arquivo externo com a marcação no <elemento appSettings> . O runtime ignorará o atributo de arquivo se o arquivo especificado não puder ser encontrado.

Aviso

Segurança – não adicione seus segredos .config arquivo ao seu projeto ou marcar-o no controle do código-fonte. Por padrão, o Visual Studio define o Build Action como Content, o que significa que o arquivo é implantado. Para obter mais informações, consulte Por que todos os arquivos na pasta do meu projeto não são implantados? Embora você possa usar qualquer extensão para os segredos .config arquivo, é melhor mantê-lo .config, pois os arquivos de configuração não são atendidos pelo IIS. Observe também que o arquivo AppSettingsSecrets.config é dois níveis de diretório acima do arquivo web.config , portanto, ele está completamente fora do diretório da solução. Ao mover o arquivo para fora do diretório da solução, "git add *" não o adicionará ao seu repositório.

Trabalhando com cadeias de conexão no ambiente de desenvolvimento

O Visual Studio cria novos projetos ASP.NET que usam o LocalDB. O LocalDB foi criado especificamente para o ambiente de desenvolvimento. Ele não requer uma senha, portanto, você não precisa fazer nada para impedir que segredos sejam verificados em seu código-fonte. Algumas equipes de desenvolvimento usam as versões completas do SQL Server (ou de outro DBMS) que exigem uma senha.

Você pode usar o configSource atributo para substituir toda <connectionStrings> a marcação. Ao contrário do <appSettings>file atributo que mescla a marcação, o configSource atributo substitui a marcação. A marcação a seguir mostra o configSource atributo no arquivo web.config :

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

Observação

Se você usar o configSource atributo conforme mostrado acima para mover suas cadeias de conexão para um arquivo externo e fazer com que o Visual Studio crie um novo site, ele não poderá detectar que você está usando um banco de dados e você não terá a opção de configurar o banco de dados ao publicar no Azure no Visual Studio. Se você estiver usando o atributo , poderá usar o configSource PowerShell para criar e implantar seu site e banco de dados, ou pode criar o site e o banco de dados no portal antes de publicar.

Aviso

Segurança – ao contrário do arquivo AppSettingsSecrets.config, o arquivo de cadeias de conexão externas deve estar no mesmo diretório que o arquivo deweb.config raiz, portanto, você precisará tomar precauções para garantir que você não o marcar no repositório de origem.

Observação

Aviso de segurança no arquivo de segredos: Uma prática recomendada é não usar segredos de produção em teste e desenvolvimento. O uso de senhas de produção em teste ou desenvolvimento vaza esses segredos.

Aplicativos de console do WebJobs

O arquivoapp.config usado por um aplicativo de console não dá suporte a caminhos relativos, mas dá suporte a caminhos absolutos. Você pode usar um caminho absoluto para mover seus segredos para fora do diretório do projeto. A marcação a seguir mostra os segredos no arquivo C:\secrets\AppSettingsSecrets.config e dados não confidenciais no arquivo 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>

Implantando segredos no Azure

Quando você implanta seu aplicativo Web no Azure, o arquivo AppSettingsSecrets.config não será implantado (é isso que você deseja). Você pode acessar o Portal de Gerenciamento do Azure e defini-los manualmente para fazer isso:

  1. https://portal.azure.comAcesse e entre com suas credenciais do Azure.
  2. Clique em Procurar > Aplicativos Web e clique no nome do aplicativo Web.
  3. Clique em Todas as configurações > Configurações do aplicativo.

As configurações do aplicativo e os valores de cadeia de conexão substituem as mesmas configurações no arquivo web.config. Em nosso exemplo, não implantamos essas configurações no Azure, mas se essas chaves estivessem no arquivo web.config , as configurações mostradas no portal teriam precedência.

Uma prática recomendada é seguir um fluxo de trabalho de DevOps e usar Azure PowerShell (ou outra estrutura, como Chef ou Puppet) para automatizar a configuração desses valores no Azure. O script do PowerShell a seguir usa Export-CliXml para exportar os segredos criptografados para o 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

No script acima, 'Name' é o nome da chave secreta, como '"FB_AppSecret" ou "TwitterSecret". Você pode exibir o arquivo ".credential" criado pelo script no navegador. O snippet abaixo testa cada um dos arquivos de credencial e define os segredos para o aplicativo Web nomeado:

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

Aviso

Segurança – Não inclua senhas ou outros segredos no script do PowerShell, isso derrota a finalidade de usar um script do PowerShell para implantar dados confidenciais. O cmdlet Get-Credential fornece um mecanismo seguro para obter uma senha. O uso de um prompt de interface do usuário pode impedir o vazamento de uma senha.

Implantando cadeias de conexão do BD

As cadeias de conexão do BD são tratadas de forma semelhante às configurações do aplicativo. Se você implantar seu aplicativo Web do Visual Studio, o cadeia de conexão será configurado para você. Você pode verificar isso no portal. A maneira recomendada de definir o cadeia de conexão é com o PowerShell.

Anotações para PHP

Como os pares chave-valor para configurações de aplicativo e cadeias de conexão são armazenados em variáveis de ambiente em Serviço de Aplicativo do Azure, os desenvolvedores que usam quaisquer estruturas de aplicativo Web (como PHP) podem recuperar facilmente esses valores. Confira a postagem do blog Sites do Windows Azure do Stefan Schackow: Como as cadeias de caracteres de aplicativo e as cadeias de conexão funcionam , que mostra um snippet de código PHP para ler as configurações do aplicativo e as cadeias de conexão.

Anotações para servidores locais

Se você estiver implantando em servidores Web locais, poderá ajudar a proteger segredos criptografando as seções de configuração dos arquivos de configuração. Como alternativa, você pode usar a mesma abordagem recomendada para sites do Azure: manter as configurações de desenvolvimento em arquivos de configuração e usar valores de variáveis de ambiente para configurações de produção. Nesse caso, no entanto, você precisa escrever o código do aplicativo para funcionalidade automática em Sites do Azure: recuperar configurações de variáveis de ambiente e usar esses valores no lugar das configurações do arquivo de configuração ou usar configurações de arquivo quando variáveis de ambiente não forem encontradas.

Recursos adicionais

Confira Sites do Windows Azure de Stefan Schackow : Como funcionam as cadeias de caracteres de aplicativo e as cadeias de conexão

Agradecimentos especiais a Barry Dorrans ( @blowdart ) e Carlos Farre pela revisão.