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

今回は以上です。