ASP.NET と Azure App Service にパスワードやその他の機密データを配置するためのベスト プラクティス
作成者: Rick Anderson
このチュートリアルでは、コードによってセキュリティ情報を安全に格納し、アクセスできるようにする方法について説明します。 最も重要なのは、パスワードやその他の機密データをソース コードに保存してはいけないこと、そして、開発およびテスト モードでは運用環境のシークレットを使用すべきでないことです。
サンプル コードは、簡単な WebJob コンソール アプリおよび ASP.NET MVC アプリであり、データベース接続文字列のパスワード、Twilio、Google、および SendGrid のセキュア キーへのアクセスが必要です。
また、オンプレミスの設定と 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 Action
が Content
に設定されます。つまり、そのファイルは配置されています。 詳細については、My Project フォルダーの一部のファイルが配置されない理由に関する記事を参照してください。"シークレットの .config" ファイルにはどの拡張子でも使用できますが、構成ファイルは IIS では提供されないため、.config をそのまま使用することをお勧めします。 また、AppSettingsSecrets.config ファイルは、web.config ファイルの 2 つ上のディレクトリ レベルにあり、ソリューション ディレクトリから完全に外れていることにも注意してください。 ソリューション ディレクトリからファイルを移動しても、それが "git add *" によってリポジトリに追加されることはありません。
開発環境で接続文字列を使用する
Visual Studio によって、LocalDB を使用する新しい ASP.NET プロジェクトが作成されます。 LocalDB は、開発環境のために特別に作成されました。 これにはパスワードが不要なので、シークレットがソース コードにチェックインされるのを防ぐための作業を行う必要はありません。 開発チームの中には、パスワードを必要とする SQL Server (またはその他の DBMS) の通常版を使用しているところもあります。
configSource
属性を使用して、<connectionStrings>
マークアップ全体を置き換えることができます。 マークアップをマージする <appSettings>
file
属性とは異なり、 configSource
属性はマークアップを置き換えます。 次のマークアップは、web.config ファイル内の configSource
属性を示しています。
<connectionStrings configSource="ConnectionStrings.config">
</connectionStrings>
Note
上記のように configSource
属性を使用して接続文字列を外部ファイルに移動し、Visual Studio で新しい Web サイトを作成すると、データベースを使用していることが検出されず、Visual Studio から Azure に発行するときに、データベースを構成するオプションが表示されません。 configSource
属性を使用している場合は、PowerShell を使用して Web サイトとデータベースを作成し、配置できます。また、発行する前にポータルで Web サイトとデータベースを作成することもできます。
警告
セキュリティ - AppSettingsSecrets.config ファイルとは異なり、外部接続文字列ファイルは、ルートの web.config ファイルと同じディレクトリに存在する必要があるため、ソース リポジトリにチェックインしないよう予防策を講じる必要があります。
Note
シークレット ファイルに関するセキュリティ警告: セキュリティのベスト プラクティスは、テストおよび開発では運用環境のシークレットを使用しないことです。 テストまたは開発で運用環境のパスワードを使用すると、そのシークレットが漏洩します。
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 の管理ポータルに移動すると、それが配置されるように手動で設定できます。
- https://portal.azure.com に移動し、Azure の資格情報でサインインします。
- [参照] > [Web アプリ] の順にクリックし、Web アプリの名前をクリックします。
- [すべての設定] > [アプリケーション設定] の順にクリックします。
アプリの設定と接続文字列の値は、web.config ファイル内の同じ設定をオーバーライドします。 この例では、こうした設定を Azure に配置しませんでしたが、これらのキーが web.config ファイルにある場合は、ポータルに表示される設定が優先されます。
ベスト プラクティスは、DevOps ワークフローに従って、Azure PowerShell (または Chef や Puppet などの別のフレームワーク) を使って、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 など) を使用する開発者は、これらの値を簡単に取得できます。 Stefan Schackow の Windows Azure Web サイト: アプリケーション文字列と接続文字列のしくみに関するブログ記事を参照してください。この記事には、アプリ設定と接続文字列を読み取る PHP スニペットが示されています。
オンプレミス サーバーに関する注意事項
オンプレミスの Web サーバーに配置する場合、構成ファイルの構成セクションを暗号化することで、シークレットをセキュリティで保護することができます。 また、Azure Web サイトで推奨されているものと同じアプローチを使用でき、開発設定を構成ファイルに保持し、運用環境の設定に環境変数の値を使用することができます。 ただし、この場合は、Azure Web サイトで自動機能のアプリケーション コードを記述する必要があり、環境変数から設定を取得し、その値を構成ファイル設定の代わりに使用します。また、環境変数が見つからないときは、構成ファイル設定を使用します。
その他のリソース
Stefan Schackow の Windows Azure Web サイト: アプリケーション文字列と接続文字列のしくみに関する記事を参照してください
レビューしていただいた Barry Dorrans (@blowdart) と Carlos Farre に感謝します。