2015/10/28

[Tomcat][鯖]Tomcat でクライアント認証

概要

環境構築

作業ディレクトリ作成

$ cd ~/tmp/ssl
$ mkdir ca
$ mkdir ca/newcerts ca/crl ca/private client
$ touch ca/index.txt
$ echo 00 > ca/serial
$ echo 00 > ca/crlnumber
$ cp /usr/ssl/openssl.cnf ./

dir を ca の絶対パスに修正

$ vim ./openssl.cnf

CA 環境構築

CA 秘密鍵を作成

$ openssl genrsa -out ca/private/cakey.pem 2048 -config openssl.cnf

CA 証明書要求を作成

$ openssl req -new -key ca/private/cakey.pem -out ca/cacsr.pem -config openssl.cnf
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:Minato-ku
Organization Name (eg, company) [Internet Widgits Pty Ltd]:foo
Organizational Unit Name (eg, section) []:bar
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

CA 証明書を作成

$ openssl x509 -req -in ca/cacsr.pem -signkey ca/private/cakey.pem -out ca/cacert.pem

クライアント環境構築

クライアント秘密鍵作成

$ openssl genrsa -out client/clientkey.pem 2048 -config ./openssl.cnf

クライアント証明書要求を作成

$ openssl req -new -key client/clientkey.pem -out client/clientcsr.pem -config ./openssl.cnf
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:Minato-ku
Organization Name (eg, company) [Internet Widgits Pty Ltd]:foo
Organizational Unit Name (eg, section) []:bar
Common Name (e.g. server FQDN or YOUR name) []:localhost
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

クライアント証明書作成

クライアントから csr を受け取った CA がやる作業。

$ openssl ca -config ./openssl.cnf -out client/client.crt -infiles client/clientcsr.pem
Using configuration from ./openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 0 (0x0)
        Validity
            Not Before: Oct 27 17:33:35 2015 GMT
            Not After : Oct 26 17:33:35 2016 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = foo
            organizationalUnitName    = bar
            commonName                = localhost
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                E1:44:51:CF:68:FC:3D:E1:52:59:F3:C3:E9:09:B4:64:CC:81:47:7C
            X509v3 Authority Key Identifier:
                DirName:/C=JP/ST=Tokyo/L=Minato-ku/O=foo/OU=bar/CN=localhost
                serial:E3:E6:4D:2B:0C:20:5A:E2

Certificate is to be certified until Oct 26 17:33:35 2016 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

サーバー環境構築

サーバー秘密鍵とキーストア作成

$ keytool -genkey -alias tomcat -keyalg RSA -keystore ../../.keystore
キーストアのパスワードを入力してください:  changeit
新規パスワードを再入力してください: changeit
姓名は何ですか。
  [Unknown]:  localhost
組織単位名は何ですか。
  [Unknown]:  bar
組織名は何ですか。
  [Unknown]:  foo
都市名または地域名は何ですか。
  [Unknown]:  Minato-ku
都道府県名または州名は何ですか。
  [Unknown]:  Tokyo
この単位に該当する2文字の国コードは何ですか。
  [Unknown]:  JP
CN=localhost, OU=bar, O=foo, L=Minato-ku, ST=Tokyo, C=JPでよろしいですか。
  [いいえ]:  y

<tomcat>の鍵パスワードを入力してください
        (キーストアのパスワードと同じ場合はRETURNを押してください):

サーバー証明書要求作成

$ keytool -certreq -alias tomcat -file tomcat.csr -keystore ../../.keystore

サーバー証明書作成

サーバーから csr を受け取った CA がやる作業。

$ openssl ca -policy policy_anything -config ./openssl.cnf -out tomcat.crt -infiles tomcat.csr
Using configuration from ./openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Oct 27 17:47:23 2015 GMT
            Not After : Oct 26 17:47:23 2016 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            localityName              = Minato-ku
            organizationName          = foo
            organizationalUnitName    = bar
            commonName                = localhost
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                5A:E0:56:79:25:16:46:39:DD:33:89:59:67:91:0F:5F:96:49:CB:10
            X509v3 Authority Key Identifier:
                DirName:/C=JP/ST=Tokyo/L=Minato-ku/O=foo/OU=bar/CN=localhost
                serial:E3:E6:4D:2B:0C:20:5A:E2

Certificate is to be certified until Oct 26 17:47:23 2016 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

サーバーキーストアにCA証明書をインポート

$ keytool -import -alias ca -trustcacerts -file ./ca/cacert.pem -keystore ../../.keystore
キーストアのパスワードを入力してください:  changeit
所有者: CN=localhost, OU=bar, O=foo, L=Minato-ku, ST=Tokyo, C=JP
発行者: CN=localhost, OU=bar, O=foo, L=Minato-ku, ST=Tokyo, C=JP
シリアル番号: e3e64d2b0c205ae2
有効期間の開始日: Wed Oct 28 02:28:40 JST 2015終了日: Fri Nov 27 02:28:40 JST 2015
証明書のフィンガプリント:
         MD5:  5C:16:AC:D6:25:3D:59:23:1B:C1:CF:F1:51:A1:6A:4B
         SHA1: 4B:C2:E7:3D:21:71:6E:C7:29:5A:34:67:9A:0C:E1:30:E8:B2:C2:19
         SHA256: DA:4B:2C:07:86:D3:93:2C:A9:74:28:54:D5:5D:77:83:3F:85:D9:01:8D:34:98:99:BD:BF:51:AC:84:59:10:91
         署名アルゴリズム名: SHA256withRSA
         バージョン: 1
この証明書を信頼しますか。 [いいえ]:  y
証明書がキーストアに追加されました

サーバーキーストアにサーバー証明書をインポート

$ keytool -import -alias tomcat -trustcacerts -file ./tomcat.crt -keystore ../../.keystore
キーストアのパスワードを入力してください:  changeit
証明書応答がキーストアにインストールされました

Tomcat 設定

server.xml

redirectPort を削除。

    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1"/>

追加。

    <Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
               maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
               clientAuth="true" sslProtocol="TLS" truststoreFile= "C:/Users/mikoto/.keystore"
               truststorePass="changeit"/>

web.xml

web-app タグの末尾に追加。

<login-config>
    <auth-method>CLIENT-CERT</auth-method>
</login-config>

wget してみる

$ # クライアント証明書による認証で失敗する
$ wget https://localhost:8443/
--2015-10-28 03:05:42--  https://localhost:8443/
localhost (localhost) をDNSに問いあわせています... ::1, 127.0.0.1
localhost (localhost)|::1|:8443 に接続しています... 接続しました。
OpenSSL: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate
SSL による接続が確立できません。
$
$
$ # クライアント証明書を指定して接続しに行く。
$ # サーバ証明書が信用できない証明書なので失敗する
$ wget https://localhost:8443/ --private-key=client/clientkey.pem --certificate=client/client.crt
--2015-10-28 03:07:46--  https://localhost:8443/
localhost (localhost) をDNSに問いあわせています... ::1, 127.0.0.1
localhost (localhost)|::1|:8443 に接続しています... 接続しました。
エラー: localhost の証明書(発行者: `CN=localhost,OU=bar,O=foo,L=Minato-ku,ST=Tokyo,C=JP')の検証に失敗しました:
  自己署名証明書です。
localhost に安全の確認をしないで接続するには、`--no-check-certificate' を使ってください。
$
$
$ # クライアント証明書とCA証明書を指定して接続しに行く
$ # サーバ証明書がCAに信用されているので接続できる
$ wget https://localhost:8443/ --private-key=client/clientkey.pem --certificate=client/client.crt --ca-certificate=ca/cacert.pem
--2015-10-28 03:09:41--  https://localhost:8443/
localhost (localhost) をDNSに問いあわせています... ::1, 127.0.0.1
localhost (localhost)|::1|:8443 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 404 Not Found
2015-10-28 03:09:41 エラー 404: Not Found。