Windows Azureで接続文字列をセキュアに扱う方法

この投稿は、Securing Your Connection String in Windows Azure: Part 1からSecuring Your Connection String in Windows Azure: Part 4までの全4回の記事を意訳したものです。一部、表現を変えてるところがありオリジナルと異なる箇所があります。

SQL Azure環境をセキュアに取り扱おうには、SQL Azureへの接続文字列をセキュアに扱う必要があります。Windows AzureでSQL Azureに接続するアプリケーションを動作させるには、Windows Azureのコードに接続文字列を組み込まなければなりません。しかし、Windows Azureのパッケージを作成する開発者に本番環境のデータベースのパスワードを教えたく無い場合があります。
この投稿では、Windows Azure環境で、SQL Azureへの接続文字列をセキュアに扱う方法について説明します。

接続文字列は、ログインIDとパスワードを含んでおり、通常は平文の文字列です。この投稿の目的は、Windows Azureからデータベースに接続するアプリケーションで、プログラムは接続文字列を認識でき、開発者には読めないように暗号化することです。暗号化した接続文字列をアプリケーションが解読できるようにキーを予めWindows Azureに持たせる必要があります。かつ開発者には知ることができないようにする必要があります。

Windows Azure Certificatesを使用する

Windows Azureのみ知ることができるキーとして、Windows Azure Cetificationsに証明書を登録します。証明書には、公開鍵暗号の秘密キーが含まれます。Windows Azureは、暗号化された接続文字列を秘密キーで解読します。公開鍵は、接続文字列を暗号化する必要がある人に配布します。公開鍵を使用して接続文字列を暗号化できても、暗号化された接続文字列を読むことはできません。

この方法では、役割に応じて3種類のユーザーにわけることができます。

  1.  秘密キーの持ち主(Windows Azure管理者) 公開キー・秘密キーを作成し、秘密キーをWindows Azureに配置します。このユーザとWindows Azureだけが接続文字列を復号化することができます。
  2.  SQL Azure管理者 接続文字列を知ることができ、Windows Azure管理者から渡された公開鍵で接続文字列を暗号化します。暗号化されたバイトを、開発者に渡します。
  3.  開発者 Windows Azureパッケージを作成し、公開鍵を知ることができます。しかし、接続文字列や秘密鍵、SQL Azureのパスワードを知ることはできません。

1. 証明書を作成する (Azure管理者)

最初に、Windows Azure管理者がローカルマシンで証明書を作成します。作成するために、Visual Studio 2008 か 2010 をインストールします。makecert.exeを使用して公開・秘密キーを生成します。.pxfフォーマットの自己証明書を作成します。

1. スタート→全てのプログラム→Microsoft Visual Studio 2010 →Visual Studio toolsにあるVisual Studioコマンド プロンプトを開く

2. 次のコマンドを実行します。

makecert -r -pe -n "CN=azureconfig" -sky exchange "azureconfig.cer" -sv "azureconfig.pvk"

20101123103550

3. 秘密キーをセキュアに扱う為のパスワードを入力するダイアログが表示されます。パスワードを入力します。

20101123103757

20101123103823

4. azureconfig.cer (公開鍵証明書)とazureconfig.pvk (秘密鍵ファイル)が生成されます

5. 次のコマンドを入力して、(Windows Azureに秘密キーをインポートするためのフォーマットである).pfxファイルを生成します。次のコマンドの、-piの後にパスワード文字列を入力します。

pvk2pfx -pvk "azureconfig.pvk" -spc "azureconfig.cer" -pfx "azureconfig.pfx" -pi パスワード文字列

6. Visual Studio コマンド プロンプトのカレントディレクトリに証明書が作成されていることを確認します。

20101123104501 

2. Windows Azureに秘密鍵をインポートする (Azure管理者)

Windows Azure管理者は、Windows Azureに秘密鍵をアップロードする必要があります。

1. Webブラウザで、Windows Azure Developer Portalにアクセスします。

2. デプロイ先のホストサービスを選択します。CertificatesManageを選択します。

 

3. 秘密鍵を選択し、秘密鍵を生成する際に入力したパスワードを入力しアップロードします。

 

4. web.configファイルで使用するので、Thumbprint文字列をコピーします。

Thumbprintは、証明書をSHA-1でハッシュ化したものを含む16進数の文字列です。Windows Azureで動作するコードが、それを使用することで、Windows Azure上にインストールされた秘密鍵にアクセスすることができます。Thumbprintは誰でも見ることができますが、秘密鍵にアクセスして接続文字列を復号化できるのは、コードだけです。

3. ユーザー権限を制限する (SQL Azure管理者)

本番環境のデータベースをより安全に運用するために、接続文字列で使用するユーザの権限を制限します。接続文字列で使用するユーザーに、SQL Azureデータベース管理者を使用してはいけません。web roleが必要な権限だけを持ったユーザを別途作成します。

もしwebサイトで、テーブルを作成する必要が無いのなら、ユーザーにテーブルを作成する権限を与えてはいけません。もしwebサイトがデータを読み込むだけでいいのなら、read権のみを与えたユーザを作成します。接続文字列に問題が発生しても、データベースに与えるダメージを減らすために、ユーザ権限を減らしておきます。

SQL Azureのユーザー作成方法については、この投稿を読んでください。

4. 公開鍵をインポートする (SQL Azure管理者)

SQL Azure管理者は、Windows Azure管理者から公開鍵を受け取り、ローカルマシーンのローカル証明書ストアにインポートします。ローカルの証明書ストアを使用して、web.configを暗号化するaspnet_regiis.exeを使用します。

1. ファイル名を指定して実行するで、mmcと入力し、Enterを押します。

20101123114009

 

2. ファイル→スナップインの追加と削除を選択する。

20101123114130

 

3. 利用できるスナップインから、証明書を選択しダブルクリックします。

20101123114210

 

4. コンピューターアカウントを選択し、次へをクリックします

20101123114313

 

5. ローカルコンピューターを選択し、完了をクリックします。

6. 証明書の下の個人を選択し、右クリックする。コンテキストメニューからすべてのタスク→インポートをクリックする。.cerファイルを選択し、インポートします。

000002

 

7. インポートした証明書を選択し、右クリックし、開くを選択する。

000003

 

開いたダイアログの詳細タブを選択する。スクロールを一番下に下げて、拇印を選択し、文字列をコピーします。拇印は後で使用します。

20101123115000 

5. プロバイダーをダウンロードしコンパイルする (SQL Azure管理者)

可能であれば、開発者がSQL Azure管理者に2つのファイル(setup.exeとinstaller.msi)をメールで送付します。無理であれば、SQL Azure管理者がプロバイダーをダウンロードし、コンパイルする必要があります。この作業には、Visual Studio 2008か2010が必要になります。

  1. Pkcs12 Protected Configuration Providerからzipファイルをダウンロードします。
  2. zipファイルを解凍します。
  3. PKCS12ProtectedConfigurationProvider.slnを探し、Visual Studioで開きます。
    なお、2008形式で作成されているソリューションなので、2010で開く場合は、ダブルクリックで開かず、Visual Studioから開いて変換ウィザードに2010形式に変換する必要があります。
  4. ツールメニューのビルド→ソリューションのビルドを選択します。
    なお、次のステップで目的の物が見当たらない場合は、Installerプロジェクトを再度ビルドします。
  5. Installer/bin/releaseディレクトリにsetup.exeが生成されていることを確認します。
  6. setup.exeを実行し、プロバイダーをインストールします。

Pkcs12CertProtectedConfiguratoinProvider.dllがグローバルアセンブリキャッシュに登録され、web.configを暗号化するときに、aspnet_regiis.exeから使用できるようになります。

6. web.configを暗号化する

接続文字列を含んだweb.configを暗号化します。

1. 開発者からweb.configを受け取ります。

2. web.configファイルに、以下のようにconnectionStringを追加します。

<connectionStrings>
  <add name="SQLAzureConn" 
       connectionString="Initial Catalog=aspnetdb;data source=.;uid=user;pwd=secretpassword" providerName="System.Data.SqlClient"/>
</connectionStrings>

接続文字列は、SQL Azure Portalから取得することができます。下の画像で示したボタンをクリックすると表示されます。

20101123123545

 

4. カスタムプロテクトプロバイダーの設定を追加します。下のように、<configProtectedData>セクションをweb roleのweb.configに追加します。thumbprintは、先にコピーしておいた拇印からスペースを除いたものを設定します。

<configProtectedData>
    <providers>
      <add name="CustomProvider" thumbprint="4badf1eea9666d95c1c046fde32008c5e3bf20d9"
           type="Pkcs12ProtectedConfigurationProvider.Pkcs12ProtectedConfigurationProvider, PKCS12ProtectedConfigurationProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34da007ac91f901d"/>
    </providers>
  </configProtectedData>

5. Visual Studioコマンドプロンプトで、カスタムプロバイダーを使用して、connectionStringsセクションを暗号化します。Visual Studioコマンドプロンプトのカレントディレクトリにweb.configを格納します。次のコマンドを実行します。

aspnet_regiis -pef "connectionStrings" "." -prov "CustomProvider"

実行し成功すると以下のような出力が表示されます。

20101123125455

コマンドを実行すると以下のような処理が行われます。

  • aspnet_regiis.exeがカレントディレクトリのweb.configを探し、読み込みます。
  • -provオプションを使用していると、configProtectedDataで、providerセクションを探し、プロバイダーのアセンブリを読み込みます。
  • aspnet_regiis.exeは、グローバルアセンブリキャッシュからアセンブリをロードし、Initializeメソッドを実行します。web.configファイルにthumbprintプロパティがあるかを確認します。
  • aspnet_regiis.exeは、Pkcs12CertProtectedConfiguratoinProvider.dllのEncryptメソッドを実行し、証明書ストアからthumbprintをキーに公開証明書を呼び出します。-pefオプションでweb.configのconnection stringセクションを読み込み、暗号化します。
  • 暗号化したconnection stringセクションをweb.configに戻します。
      <connectionStrings configProtectionProvider="CustomProvider">
        <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
          xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes192-cbc" />
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
              <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
              <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                <KeyName>rsaKey</KeyName>
              </KeyInfo>
              <CipherData>
                <CipherValue>aA4kyC0pNY8VFnPtLcC...=</CipherValue>
              </CipherData>
            </EncryptedKey>
          </KeyInfo>
          <CipherData>
            <CipherValue>6Fg9VWR5/...</CipherValue>
          </CipherData>
        </EncryptedData>
      </connectionStrings>

6. web.configを開発者に返します。

7. プロバイダーをダウンロードしコンパイルする (開発者)

web roleプロジェクトでコンパイルされたプロバイダーを参照する必要があります。

  1. Pkcs12 Protected Configuration Providerからzipファイルをダウンロードします。
  2. zipファイルを解凍します。
  3. PKCS12ProtectedConfigurationProvider.slnを探し、Visual Studioで開きます。

    なお、2008形式で作成されているソリューションなので、2010で開く場合は、ダブルクリックで開かず、Visual Studioから開いて変換ウィザードに2010形式に変換する必要があります。
  4. ツールメニューのビルド→ソリューションのビルドを選択します。
  5. PKCS12ProtectedConfigurationProvider\bin\Release ディレクトリにPKCS12ProtectedConfigurationProvider.dll があることを確認します。
  6. PKCS12ProtectedConfigurationProvider.dllをコピーし、web roleに配置します。

8. プロバイダーを使用してプロジェクトを更新する (開発者)

1. web roleプロジェクトにPKCS12ProtectedConfigurationProvider.dllアセンブリ参照を追加します。web roleプロジェクトを右クリックし、参照の追加をクリックします。Pkcs12CertProtectedConfiguratoinProvider.dllを選択し、追加します。Pkcs12CertProtectedConfiguratoinProvider.dllを選択し、右クリックからプロパティを選択します。ローカルコピーをTrueに変更します。これは、Windows Azureにアセンブリファイルをデプロイするのに必要な操作です。

000004

 

2. Windows Azure管理者から、Windows Azure Portalから秘密鍵のthumbprintを受け取ります。

web.configのthumbprintをWindows Azure Portalから取得したthumbprintに置き換えます。接続文字列を復号化するには、秘密鍵のthumbprintが必要になります。

以上で、web.configの接続文字列をPKCS12ProtectedConfigurationProvider.dllで暗号化できたので、パッケージをWindows Azureにデプロイします。

コードレビュー

接続文字列にアクセスするには、次のようなコードを書きます。

Response.Write("Clear text connection string is: " +
                 System.Web.Configuration.WebConfigurationManager.ConnectionStrings
                            ["SQLAzureConn"].ConnectionString);