Do what you want to do

プログラミングとかとか

Azure Web RoleでSSLクライアント証明書認証を使用する方法

今回はAzureネタです。
とある案件でAzure Web Roleで稼働しているWebサービスSSLクライアント証明書認証を実装することになり、初めての経験だったのでやったことの記録を残しておきたいと思います。

前提

まず前提として対象のWebサービスは既にHTTPS通信に対応してました。(証明書はオレオレ証明書ですが...)
よってクライアント証明書認証にもオレオレ証明書を使用します。

開発環境

開発環境は以下の通りです。

IDE Microsoft Visual Studio Premium 2013
対象のフレームワーク .NET Framework 4
Microsoft Azure Tools バージョン 2.4
クラウドサービスVMオプション Web Role

やらなくてはならないこと

Web RoleでSSLクライアント証明書認証をするためには以下を行わなければいけません。

  1. Webサービスが稼働しているサーバーにルート証明書をインストール
  2. WebサービスサイトのSSL SettingsでSSLクライアント証明書認証を有効にする

上記の作業はWebサービスをAzure上にデプロイした後でもRDPが有効であれば
手動で設定可能なのですが、やっぱりデプロイ時に自動でやりたいですよね?っていうか
手動の場合はスケールアウトした時にも都度手動設定が必要になるのでクラウドのメリットをあまり受けられずイケてないですよね?

ってことでWebサービスデプロイ時に自動で設定するにはどうしたら良いか調べてみました。

証明書インストールの自動化

まず、証明書のインストールは以下の方法でスタートアップスクリプトで自動化しました。

  1. デプロイ対象のプロジェクトにStartupフォルダを作成し、その中にAddCert.cmd(コマンドファイル)とhogehoge.cloudapp.net.cer(ルート証明書)を追加。
  2. 追加した2つのファイルのプロパティで「出力ディレクトリにコピー」を「常にコピーする」に変更。
  3. AddCert.cmdに下記内容を記述する。見ての通りルート証明書として証明書を追加しているだけです。

    certutil -addstore root Startup\hogehoge.cloudapp.net.cer

  4. ServiceDefinition.csdefにスタートアップタスクの設定を行う

    <Startup>
        <Task commandLine="Startup\AddCert.cmd" executionContext="elevated" taskType="simple"></Task>
    </Startup>
    

    ここでのポイントはexecutionContextに"elevated"を指定することでスタートアップタスクが管理者特権で実行されるように指定していることです。この辺りの設定はスタートアップ タスクのベスト プラクティスをご覧ください。


SSLクライアント証明書認証有効化の自動化

こちらについては概ねこちらの記事の通りです。
スタートアップタスクでやるのはダメなの?って感じですが、スタートアップタスクはRoleのOnStartより早い段階で実行され、その段階ではまだIIS上にサイトができていないのでサイトの設定を行うにはタイミングが早すぎてNGです。RoleのOnStartでやるのがいいみたいですね。

ここで一点注意点が。
参考記事中だとsslFlagsに"Ssl,SslRequireCert"を設定していますがこれだとクライアントからのリクエストに対して常に403を返してしまいNGでした。
その理由はフラグの設定が不足しているからです。
正しくは"Ssl,SslNegotiateCert,SslRequireCert"です。

下記表はIIS ManagerからSSL Settingsを手動で設定した場合のsslFlagsの値を表したものです。
この表のRequire SSLにチェックありかつClient certificatesがRequireの状態にしたいので
"Ssl,SslNegotiateCert,SslRequireCert"を設定しないとダメということです。

Require SSL Client certificates sslFlags
チェックなし Ignore None
チェックなし Accept SslNegotiateCert
チェックあり Ignore Ssl
チェックあり Accept Ssl,SslNegotiateCert
チェックあり Require Ssl,SslNegotiateCert,SslRequireCert

今回は以上です。

Azure SDK 2.5のWADでカスタムログが転送されない問題

2015/07/14 追記:SDK 2.6ではrelativePathでログ転送できるようになったようです。

今回はAzureネタです。
親切な方がこちらのブログでAzure SDK 2.5のDiagnosticsへの移行方法をまとめて下さっています。

私もSDK2.5にアップグレードしてWADの動作を確認してみたところ、
ローカルストレージに出力したアプリケーションのログファイルだけが
BLOBに転送されない!!!なぜだ???

ちなみにdiagnostics.wadcfgxの設定はこんな感じになっています。(該当部分のみ抜粋)

<DataSources>
  <DirectoryConfiguration containerName="customlog">
    <LocalResource name="LogStore" relativePath="."/>
  </DirectoryConfiguration>
</DataSources>

LocalResource指定の方法はVisual StudioGUIからは設定できないのですが、wadcfgxを直接編集することで設定できるんですよね~。(参考)

自分だけかと思って他の方にも確認していただいたところ、同じように転送できないそうなのでSDK2.5のバグかもしれません。。

現時点での対応としてはVisual StudioGUIから設定できる絶対パスで設定するしかないようです。

<DataSources>
  <DirectoryConfiguration containerName="customlog">
    <Absolute path="C:\Resources\directory\<ロールのデプロイID>.<ロール名>.<ローカルストレージ名>" expandEnvironment="false"/>
  </DirectoryConfiguration>
</DataSources>

ちなみにAbsoluteの方法では環境変数が使えないバグ?があるみたいなので注意が必要です。
普通、Absoluteの方法では環境変数の値を使ってC:\Resources\Directory\%RoleDeploymentID%.%RoleName%.<ローカルストレージ名>のように設定すると思いますがこれだとうまく転送されません。ロールのデプロイIDやロール名をハードコードする必要があります。

2015年12月9日の対応期限までにこれらのおかしな問題が修正されれば良いのですが。