Apache でクライアント認証を実現する

Web サーバの設定

ここでは、Apache (2.4以降) を用いて、SSL Web サイトでクライアント認証を実現する方法を説明します。既存の ID・パスワードだけの Web サイトにこの設定を導入するだけで、あらかじめ証明書を配ったユーザしかアクセスできない、二要素認証化が実現できます。

この設定例では、クライアント証明書に JCAN証明書を用います。

JCAN証明書とは

クライアント証明書の、ルート証明書の用意

まず、認証するクライアント証明書の、ルート証明書および中間証明書 (PEM 形式) を用意します。JCAN証明書の場合は、

https://www.jipdec.or.jp/repository/

より「GlobalSignルートCA – R3(GMOグローバルサイン社)」および「Trusted Root CA SHA256 G2(GMOグローバルサイン社)」の 2つのファイルをダウンロードします。この 2つのテキストファイルを連結し、ひとつのファイルとして保存、Web サーバの /etc/httpd/cert/globalsign-root.pem などとして配置します。ディレクトリは任意です。

# cat /etc/httpd/cert/globalsign-root.pem
-----BEGIN CERTIFICATE-----
MIIEXDCCA0SgAwIBAgILBAAAAAABNumCOV0wDQYJKoZIhvcNAQELBQAwTDEgMB4G
A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
...
rc2yJS70DvfkPiEnBJ2x2AHZV3yKTALUqurkV705JledqUT9I5frAwYNXZ8pNzde
n+DIcSIo7yKy6MX9czbFWQ==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
...
mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH

クライアント認証範囲の設定

次に、Web サーバの SSL 設定を変更します。ここで、クライアント認証の対象とする URL の範囲を指定します。

[/etc/httpd/conf.d/ssl.conf

<VirtualHost *:443>
  ServerName www.example.net:443
  ...
  SSLCACertificateFile /etc/httpd/cert/globalsign-root.pem
  ...
  <Location /test>  # 対象となるディレクトリを指定
    SSLVerifyClient require
    SSLVerifyDepth 10
    SSLRequire (%{SSL_CLIENT_S_DN_O} eq "InfraWare, Inc." and \
        %{SSL_CLIENT_I_DN_OU} eq "JCAN Public CA1 - G4")
  </Location>
</VirtualHost>

Location に続いてクライアント認証をするディレクトリを指定します。上の例では、https://www.example.net/test/ 以下にアクセスすると、クライアント証明書が求められます。

SSLRequre に続く条件式は、クライアント証明書に記載されている内容を比較し、その条件にマッチした場合にのみ、認証が通る、という設定を表しています。上の例では、発行者の OU が “JCAN Public CA1 – G4” であり、証明書の O が “InfraWare, Inc.” であること、すなわち当社で発行した JCAN証明書であることを求めています。

また、

SSLRequire (%{SSL_CLIENT_S_DN_CN} =~ /BN-.*\(ExampleInc\).*/  and \
  %{SSL_CLIENT_S_DN_O} eq "InfraWare, Inc." and \
  %{SSL_CLIENT_I_DN_OU} eq "JCAN Public CA1 - G4")

のように書けば、当社で ExampleInc 社向けに発行した JCAN証明書を持っているユーザだけがアクセスできます。

当社で発行する JCAN証明書の CN (Common Name) の最後には、部署名や社員番号などを申し込み時に指定することができます。これらを判定条件に使っても良いでしょう。

条件式に利用できる SSL_CLIENT_S_DN_O などの変数については、事項をご覧ください。

PHP で認証したクライアント証明書の中身を調べる

PHP で書かれたページからは、以下のように $_SERVER 変数でクライアント証明書の内容が取り出せます。SSL_CLIENT_S で始まるものが所有者の情報、SSL_CLIENT_I で始まるものが発行者 (JCAN証明書の場合は JIPDEC) となります。この変数名はすべて、前項の SSLRequire の式で用いることができます。

SSL_CLIENT_S_DN CN=BN-Fujiwara.Toshiki(InfrawareInc)-RD001,O=InfraWare\, Inc.,OU=OU1-x.x.xxx.xxxxxx.xx.xx.x(JCAN Certified),OU=OU2-xxxxxxxx-xxxxxx-x-CN-1020002058892,L=Yokohama,ST=Kanagawa,C=JP
SSL_CLIENT_S_DN_C JP
SSL_CLIENT_S_DN_ST Kanagawa
SSL_CLIENT_S_DN_L Yokohama
SSL_CLIENT_S_DN_CN BN-Fujiwara.Toshiki(InfrawareInc)-RD001
SSL_CLIENT_S_DN_O InfraWare, Inc.
SSL_CLIENT_S_DN_OU OU2-xxxxxxxx-xxxxxx-x-CN-1020002058892
SSL_CLIENT_S_DN_OU_1 OU1-x.x.xxx.xxxxxx.xx.xx.x(JCAN Certified)
SSL_CLIENT_SAN_Email_0 toshi-f@infra-ware.net
SSL_CLIENT_I_DN CN=JCAN Public CA1 – G4,OU=JCAN Public CA1 – G4,O=JIPDEC,C=JP
SSL_CLIENT_I_DN_C JP
SSL_CLIENT_I_DN_CN JCAN Public CA1 – G4
SSL_CLIENT_I_DN_O JIPDEC
SSL_CLIENT_I_DN_OU JCAN Public CA1 – G4
SSL_CLIENT_VERIFY SUCCESS
SSL_CLIENT_V_START Sep 6 14:22:02 2019 GMT
SSL_CLIENT_V_END Sep 30 14:59:59 2020 GMT

ユーザ側 (クライアント) の設定

つぎに、ユーザ側 (認証を受ける側) の設定を説明します。ユーザ側は、自身の証明書をデバイスにインストールするだけです。デバイス環境・ブラウザによって多少操作方法が異なります。

Chrome / Edge の場合

Windows の証明書チェインの「自分用の証明書」にインストールするだけで、これらのブラウザが認識してくれます。

  1. コントロールパネルから「ユーザ証明書の管理」を起動します。
  2. 証明書ストアから [個人] の [証明書] を選択します。
  3. [インポート] を実行します。
  4. この画面では単に [次へ] をクリックし、進みます。
  5. [参照] をクリックし、自身の証明書ファイル (pfx) を指定します。
  6. 証明書のパスフレーズ (PIN) を、[パスワード] 欄に入力します。
    [このキーをエクスポート可能にする] をチェックしておくと、証明書ストアから後でエクスポートすることも可能です (必須ではありません)。
  7. [証明書を次のストアに配置する] [個人] を選択し、[次へ] 進みます。
  8. これで証明書の設定 (インポート) は完了です。
    証明書ストアの自身の証明書一覧に加わっていることを確認しましょう。

自身の証明書をインストールし、クライアント認証が要求される Web サイトにアクセスすると、以下のように証明書ストアの中から適合する証明書が表示されます。[OK] をクリックするれば、認証され、Web コンテンツにアクセス可能になります (下の例は Chromium Edge です)。

Firefox の場合

Firefox の場合は、ブラウザの設定で、ブラウザ自身に証明書をインストールする必要があります。

  1. Firefox の設定アイコンから [オプション] を選択、さらに左側のメニューから [プライバシーとセキュリティ] をクリックします。
    証明書の項にある [証明書を表示] ボタンをクリックしてください。
  2. [あなたの証明書] タブを選択すると、現在インストールされているクライアント証明書が一覧されます。ここで、[インポート] ボタンをクリックします。
  3. インポートする証明書ファイルの選択画面になりますので、自身の証明書ファイル (pfx) を指定します。
    その後、パスワードを求められますので (下図)、証明書のパスフレーズ (PIN) を入力します。
  4. 証明書の設定 (インポート) は完了です。
    証明書ストアの自身の証明書一覧に加わっていることを確認しましょう。

自身の証明書をインストールし、クライアント認証が要求される Web サイトにアクセスすると、以下のように証明書ストアの中から適合する証明書が表示されます。[OK] をクリックするれば、認証され、Web コンテンツにアクセス可能になります。