ASP.NET と Azure App Service にパスワードやその他の機密データを配置するためのベスト プラクティス

作成者 : Rick Anderson

このチュートリアルでは、コードがセキュリティで保護された情報を安全に格納してアクセスする方法について説明します。 最も重要な点は、パスワードやその他の機密データをソース コードに保存しないでください。また、開発およびテスト モードでは運用シークレットを使用しないでください。

サンプル コードは、単純な WebJob コンソール アプリと、パスワード、Twilio、Google、SendGrid のセキュリティで保護されたキー接続文字列データベースにアクセスする必要がある ASP.NET MVC アプリです。

オンプレミスの設定と PHP についても説明されています。

開発環境でのパスワードの操作

チュートリアルでは、多くの場合、ソース コードに機密データが表示されます。できれば、ソース コードに機密データを格納しないでください。 たとえば、 SMS と電子メール 2FA を使用した私の ASP.NET MVC 5 アプリ のチュートリアルでは、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>

web.config ファイルはソース コードであるため、これらのシークレットをそのファイルに格納しないでください。 幸いなことに、 <appSettings> 要素には、機密性の file 高いアプリ構成設定を含む外部ファイルを指定できる属性があります。 外部ファイルがソース ツリーにチェックインされていない限り、すべてのシークレットを外部ファイルに移動できます。 たとえば、次のマークアップでは、 AppSettingsSecrets.config ファイルにすべてのアプリ シークレットが含まれています。

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

外部ファイル (このサンプル ではAppSettingsSecrets.config ) のマークアップは、 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>

ASP.NET ランタイムは、外部ファイルの内容を appSettings> 要素の<マークアップとマージします。 指定したファイルが見つからない場合、このファイル属性は無視されます。

警告

セキュリティ - シークレット .config ファイルをプロジェクトに追加したり、ソース管理にチェックしたりしないでください。 既定では、Visual Studio は を Build ActionContent設定します。これは、ファイルがデプロイされていることを意味します。 詳細については、「 プロジェクト フォルダー内のすべてのファイルが配置されない 理由」を参照してください。 シークレット .config ファイルには任意の拡張子を使用できますが、構成ファイルは IIS によって提供されないため .configに維持することをお勧めします。 また、AppSettingsSecrets.config ファイルは、web.config ファイルから 2 つのディレクトリ レベル上にあるため、ソリューション ディレクトリから完全に外れていることに注意してください。 ソリューション ディレクトリからファイルを移動しても、"git add *" ではリポジトリに追加されません。

開発環境での接続文字列の操作

Visual Studio では、 LocalDB を使用する新しい ASP.NET プロジェクトが作成されます。 LocalDB は、開発環境専用に作成されました。 パスワードは必要ないため、シークレットがソース コードにチェックインされるのを防ぐために何もする必要はありません。 一部の開発チームでは、パスワードを必要とするフル バージョンのSQL Server (またはその他の DBMS) を使用しています。

属性を configSource 使用して、マークアップ全体 <connectionStrings> を置き換えることができます。 マークアップを <appSettings>file マージする属性とは異なり、 属性は configSource マークアップを置き換えます。 次のマークアップは、 configSourceweb.config ファイル内の 属性を示しています。

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

注意

上記のように 属性を configSource 使用して接続文字列を外部ファイルに移動し、Visual Studio で新しい Web サイトを作成した場合、データベースを使用していることを検出できず、Visual Studio から Azure に発行するときにデータベースを構成するオプションは表示されません。 属性を configSource 使用している場合は、PowerShell を使用して Web サイトとデータベースを作成して展開するか、発行する前にポータルで Web サイトとデータベースを作成できます。

警告

セキュリティ - AppSettingsSecrets.config ファイルとは異なり、外部接続文字列ファイルはルート web.config ファイルと同じディレクトリに存在する必要があるため、ソース リポジトリにチェックしないように予防措置を講じる必要があります。

注意

シークレット ファイルのセキュリティ警告: ベスト プラクティスは、テストと開発で運用シークレットを使用しないことをお勧めします。 テストまたは開発で運用パスワードを使用すると、これらのシークレットが漏洩します。

WebJobs コンソール アプリ

コンソール アプリで使用される app.config ファイルは相対パスをサポートしていませんが、絶対パスをサポートします。 絶対パスを使用して、シークレットをプロジェクト ディレクトリから移動できます。 次のマークアップは、 C:\secrets\AppSettingsSecrets.config ファイル内のシークレットと、 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>

Azure へのシークレットのデプロイ

Web アプリを Azure にデプロイすると、 AppSettingsSecrets.config ファイルはデプロイされません (それが必要です)。 Azure 管理ポータルに移動し、手動で設定して、次の操作を行うことができます。

  1. https://portal.azure.com移動し、Azure 資格情報でサインインします。
  2. [参照>Web Apps] をクリックし、Web アプリの名前をクリックします。
  3. [ すべての設定] [アプリケーション設定 > ] の順にクリックします

アプリの設定接続文字列の値は、web.config ファイル内の同じ設定をオーバーライドします。 この例では、これらの設定を Azure にデプロイしませんでしたが、これらのキーが web.config ファイルにある場合は、ポータルに表示される設定が優先されます。

ベスト プラクティスは、DevOps ワークフローに従い、Azure PowerShell (または ChefPuppet などの別のフレームワーク) を使用して、Azure でのこれらの値の設定を自動化することです。 次の PowerShell スクリプトでは 、Export-CliXml を使用して、暗号化されたシークレットをディスクにエクスポートします。

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

上記のスクリプトでは、'Name' は '"FB_AppSecret" や "TwitterSecret" などの秘密キーの名前です。 スクリプトによって作成された ".credential" ファイルをブラウザーで表示できます。 次のスニペットでは、各資格情報ファイルをテストし、名前付き Web アプリのシークレットを設定します。

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

警告

セキュリティ - PowerShell スクリプトにパスワードやその他のシークレットを含めないでください。そうすると、PowerShell スクリプトを使用して機密データを展開する目的が得られません。 Get-Credential コマンドレットは、パスワードを取得するための安全なメカニズムを提供します。 UI プロンプトを使用すると、パスワードの漏洩を防ぐことができます。

DB 接続文字列のデプロイ

DB 接続文字列は、アプリ設定と同様に処理されます。 Visual Studio から Web アプリをデプロイすると、接続文字列が構成されます。 これはポータルで確認できます。 接続文字列を設定する推奨される方法は、PowerShell を使用することです。

PHP に関する注意事項

アプリ設定接続文字列の両方のキーと値のペアはAzure App Serviceの環境変数に格納されるため、任意の Web アプリ フレームワーク (PHP など) を使用する開発者は、これらの値を簡単に取得できます。 アプリの設定と接続文字列を読み取る PHP スニペットを示す「Stefan Schackow の Windows Azure Web サイト: アプリケーション文字列と接続文字列のしくみ 」ブログ記事を参照してください。

オンプレミス サーバーに関する注意事項

オンプレミスの Web サーバーにデプロイする場合は、 構成ファイルの構成セクションを暗号化してシークレットをセキュリティで保護できます。 別の方法として、Azure Websites に推奨されるのと同じ方法を使用できます。開発設定は構成ファイルに保持し、運用環境の設定には環境変数の値を使用します。 ただし、この場合は、Azure Websites で自動機能のアプリケーション コードを記述する必要があります。環境変数から設定を取得し、構成ファイル設定の代わりにこれらの値を使用するか、環境変数が見つからない場合は構成ファイル設定を使用します。

その他のリソース

「Stefan Schackow の Windows Azure Web サイト: アプリケーション文字列と接続文字列のしくみ」を参照してください

バリ・ドラン( @blowdart )とカルロス・ファーレのレビューに感謝します。