会社で使う認証局 クライアント証明書編

Alfrescoをインストールして運用を開始しようと考えた時、ケータイからのアクセス&検索が欲しくなってきた。外に居て、そういえばあのプリントに書いてあったことをど忘れした、何だっけ?となるであろうことが容易に想像できるから。自宅のデスクトップPCからはパスワードだけでアクセスでき、外に持ち出したケータイからはクライアント証明書+パスワードでアクセスできるようにすれば、だいぶ安全。

で、この設定ができれば、会社でもインターネットに口を開ける事ができるんじゃないかということで、こんなタイトルにしてみたりして…

※今回、ケータイ用のAlfrescoからのアクセスは実現できておらず、Chromeから/shareへのアクセスにとどまっている。ギリ使えるからまずはこれで。





認証局は以前の記事で構築済みの前提で、

  • クライアント証明書を発行し、認証局で承認する。
  • クライアント証明書をケータイ端末にインストールする。
  • Apacheは自宅のIPは無条件に接続可、インターネットからの接続にはクライアントの認証をする、という設定にすれば良い。
  • クライアント証明書が必要なくなったら、認証局で失効させる。

を一通り操作できれば良さそう。

 

やること

今回の記事の構成は以下。

  • クライアント証明書の発行・クライアント証明書の生成
    • クライアント証明書への署名
    • クライアント証明書と秘密鍵をPKCS#12フォーマットにまとめる
    • 配布とインストール
  • Apacheの設定
  • クライアント証明書の失効・クライアント証明書の失効と失効リストの作成
    • Apacheの設定

やっぱりそれなりに工数を掛けることになるが、ちょっと頑張れば安全が手に入ると思って頑張ることにする。

 

クライアント証明書の発行

クライアント証明書の生成

クライアント証明書を作成する用のopenssl.cnfを作成する。このCAは、今までの過程でサーバーの証明書の生成・署名をしてきているのだが、この際に使用した
 [ usr_cert ]セクションをクライアント証明書の生成でも利用しており、クライアント証明書とは設定内容がだいぶ違っているのだった。
参考: プライベート認証局(CA)にてクライアント証明書の発行

$ sudo cp /etc/ssl/openssl.cnf /etc/ssl/openssl-client.cnf

 

ファイルの中身を編集。

/etc/ssl/openssl-client.cnf
[ CA_default ]
・・・
default_days    = 3650 ← 1年から10年に設定を変更
・・・

[ usr_cert ]
・・・
nsCertType = client
subjectAltName = email:copy
#subjectAltName=@user_cert_altname ← 前回記事で定義している場合はコメントアウト
・・・

 

他はこのままで構わない模様。なお、nsCertTypeについては、emailやobjsignをカンマでつなげて記述可能なので、必要ならば加えておけば良さそう。

設定ファイルの準備ができたら、証明書を作成する。

前回は、こんな形(黒文字)でディレクトリを構成したので、新たにクライアント用にディレクトリを作成する(赤文字)。

hogeCA
├ certs/
├ newcerts/
├ crl/
├ private/
├ work/ ←作業用ディレクトリ、以下、日付と要求等。
│  ├ 20170430_esxi
│  ├ 20170501_docshare
│  └ 20710502_telecan
└ work-client/ ←作業用ディレクトリ、以下、日付と要求等。
    ├ 20170603_android1
    │  ├ newcert.pem ← 署名結果として生成される。
    │  └ newreq.pem ← 要求をこの名前で入れる。
    ├ 20170604_android2
    └ 20170605_iphone1

※認証局で証明書を作成しようとしているが、証明書の作成自体は他のサーバーで行って認証局で署名をしても良いハズ。

作業用ディレクトリで以下を実行。

$ sudo SSLEAY_CONFIG="-config /etc/ssl/openssl-client.cnf" /usr/lib/ssl/misc/CA.sh -newreq
Generating a 2048 bit RSA private key
..........................................................................+++
.............+++
writing new private key to 'newkey.pem'
Enter PEM pass phrase:[この証明書のパスワード]
Verifying - Enter PEM pass phrase:[同じのをもう一度]
-----
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) [JA]:
State or Province Name (full name) [Tokyo]:
Locality Name (eg, city) []:Akasatana
Organization Name (eg, company) [hogeserver]:←後でクライアント証明書の条件として使う
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:hogeyama hogeo
Email Address []:hogehoge@hogeserver.hogeddns.jp

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:[Enter]
An optional company name []:[Enter]
Request is in newreq.pem, private key is in newkey.pem

 

できあがったリクエストの確認。入力はこんなふうに反映される。

$ openssl req -text -noout -in newreq.pem
Certificate Request:
    Data:
        Version: 0 (0x0)
        Subject: C=JA, ST=Tokyo, L=Akasatana, O=hogeserver, CN=hogeyama hogeo/emailAddress=hogehoge@hogeserver.hogeddns.jp
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:
                      ・
                      ・
                      ・
                    XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:
                    XX:XX
                Exponent: 65537 (0x10001)
        Attributes:
            a0:00
    Signature Algorithm: sha256WithRSAEncryption
         XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:
           ・
           ・
           ・
         XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:
         XX:XX:XX:XX

 

クライアント証明書への署名

署名は認証局で行う必要があり、こちらもクライアント用のcnfファイルを使う。

$ sudo SSLEAY_CONFIG="-config /etc/ssl/openssl-client.cnf" /usr/lib/ssl/misc/CA.sh -sign
Using configuration from /etc/ssl/openssl-client.cnf
Enter pass phrase for /etc/ssl/hogeCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: NNNNNNNNNNNNNNNNNNNN (0xXXXXXXXXXXXXXXXX)
        Validity
            Not Before: Jun  2 22:09:29 2017 GMT
            Not After : May 31 22:09:29 2027 GMT
        Subject:
            countryName               = JA
            stateOrProvinceName       = Tokyo
            localityName              = Akasatana
            organizationName          = hogeserver
            commonName                = hogeyama hogeo
            emailAddress              = hogehoge@hogeserver.hogeddns.jp
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Cert Type:
                SSL Client
            Netscape Comment:
                hogeserver client certificate
            X509v3 Subject Key Identifier:
                XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
            X509v3 Authority Key Identifier:
                keyid:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX

            X509v3 Subject Alternative Name:
                email:hogehoge@hogeserver.hogeddns.jp
Certificate is to be certified until May 31 22:09:29 2027 GMT (3650 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
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: NNNNNNNNNNNNNNNNNNNN (0xXXXXXXXXXXXXXXXX)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=JA, ST=Tokyo, O=hogeserver, CN=hogeserver.hogeddns.jp/emailAddress=webmaster@hogeserver.hogeddns.jp
        Validity
            Not Before: Jun  2 22:09:29 2017 GMT
            Not After : May 31 22:09:29 2027 GMT
        Subject: C=JA, ST=Tokyo, L=Akasatana, O=hogeserver, CN=hogeyama hogeo/emailAddress=hogehoge@hogeserver.hogeddns.jp
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:
                      ・
                      ・
                      ・
                    XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:
                    XX:XX
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Cert Type:
                SSL Client
            Netscape Comment:
                hogeserver client certificate
            X509v3 Subject Key Identifier:
                XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
            X509v3 Authority Key Identifier:
                keyid:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX

            X509v3 Subject Alternative Name:
                email:hogehoge@hogeserver.hogeddns.jp
    Signature Algorithm: sha256WithRSAEncryption
         XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:
           ・
           ・
           ・
         XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:
         XX:XX:XX:XX
-----BEGIN CERTIFICATE-----
・
・
・
-----END CERTIFICATE-----
Signed certificate is in newcert.pem

 

クライアント証明書と秘密鍵をPKCS#12フォーマットにまとめる

これはには残念ながらCA.shが使えない。CA.shだとCAの秘密鍵をパッケージングしてしまうためで、ここではクライアント証明書の秘密鍵をパッケージングしたい。

$ sudo openssl pkcs12 -export -in newcert.pem -inkey newkey.pem -out newcert.pfx -name "hogeserver client certificate"
Enter pass phrase for newkey.pem:[この証明書のパスワード]
Enter Export Password:配布時のパスワード[Enter]
Verifying - Enter Export Password:配布時のパスワード[Enter]

※なお、配布時のパスワードを入れておかないと、証明書が機能してくれなかったので注意。

配布とインストール

できあがった、newcert.pfxはバイナリファイル。何らかの方法で取り出してクライアントに送る。

まずはテストとしてWindows10で取り込もうとテストしたところ、パスワード入力を求められた。パスワードを設定し、個人データとして取り込んだ。

Google Chromeでアクセスすると、使用する証明書の選択画面が表示され、この証明書を選択すればアクセスができる。IEでアクセスしてもほぼ同じ感じ。

次に、Android端末にメールで送ってみた。添付ファイルをタップすると、パスワード入力を求められた。次の問い合わせは「VPNとアプリ」か「Wifi」か?なので「VPNとアプリ」を選んでインストールした。

Chromeでアクセスすると、使用する証明書の選択画面が表示され、この証明書を選択すればアクセスできる。他のブラウザは試していないが、メジャーなものならきっと使えるだろう。

 

Apacheの設定

Apacheでクライアント証明書を利用するように設定する。既にSSLモジュールは有効になっている。

$ sudo a2enmod ssl

 

また、CAのSSL証明書を配置しておく必要がある。
/etc/ssl/private/hogeserver.hogeddns.jp.crt
として保管した。

構築したばかりのAlfrescoを接続元IPアドレス制限&クライアント認証で設定する。
参考1: ApacheでIP制限とクライアント認証をor条件で運用する
参考2: Apache Module mod_ssl
参考3: 正規表現でIPアドレスを範囲で書くときに便利なページ

諸事情により、Alfrescoの公開設定を参考に以下を新規作成、28443での公開。

/etc/apache2/sites-available/alfresco-client-auth.conf
#
# Alfresco SSL公開設定
#
Listen *:28443
<VirtualHost *:28443>

        ServerAdmin  webmaster@hogeserver.hogeddns.jp
        ServerName   docshare.hogeserver.hogeddns.jp        ※執筆時に気付いた不足設定
        DocumentRoot /var/www/html

        ErrorLog  ${APACHE_LOG_DIR}/ssl-error.log
        CustomLog ${APACHE_LOG_DIR}/ssl-access.log combined

        SSLEngine on
        SSLCertificateFile    /etc/ssl/private/docshare.crt
        SSLCertificateKeyFile /etc/ssl/private/docshare.key

        SSLCACertificateFile /etc/ssl/private/hogeserver.hogeddns.jp.crt
        SSLVerifyClient optional
        SSLVerifyDepth 1
        <Location />
                ProxyPass ajp://localhost:18009/
                SSLRequire ( %{SSL_CLIENT_S_DN_O} in {"hogeserver"} ) \      ※ココでサーバー名を使う
                        or ( %{REMOTE_ADDR} =~ m/^192\.168\.nnn\.[0-9]+$/ )  ※クライアント証明書不要のIPアドレス範囲
        </Location>

        RewriteEngine On
        RewriteCond %{HTTPS} off
        RewriteRule ^alfresco/(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L] 

</VirtualHost>

 

CA証明書を指定し、クライアント認証は必須ではなくオプションにした。

/shareと/alfrescoへのアクセスではなく、ルートから全てを18009にまかせて、そこでクライアント認証を行う。

クライアント認証の条件を、証明書のOrganization Nameが「hogeserver」であること、または、自宅内IPからのアクセスであること、とした。

IPアドレスの範囲を正規表現で書くにあたって、bitmaskによっては複雑な表記になる場合がある。このときにはGoogle先生のツールが役に立つかも。
IP アドレスの範囲を指定して、そこからのトラフィックを除外するにはどうしたらよいですか?

※なお、これだけだとクライアント証明書の失効に対応していないので注意!この後説明。

設定が終わったら、サイトを有効にして、設定をリロードすれば設定が有効になる。

$ sudo service a2ensite alfresco-client-auth.conf
$ sudo service apache2 reload

 

端末等からアクセスして試してみる。

https://docshare.hogeserver.hogeddns.jp:28443/share

 

クライアント証明書の失効

何らかの理由でクライアント証明書を失効させる場合もあるだろう。ケータイ失くしちゃった等。その場合には、

  • クライアント証明書の失効
  • 証明書の失効リストを作成
  • Apacheで失効リストを参照するよう設定

を行う。やり方はココにきっちり書かれていた。
参考: クライアント証明書環境/失効操作

クライアント証明書の失効と失効リストの作成

まず、認証局でクライアント証明書を失効させる。失効させる証明書のディレクトリに移動して…

$ sudo openssl ca -revoke newcert.pem
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/hogeCA/private/cakey.pem:
Revoking Certificate XXXXXXXXXXXXXD1A.
Data Base Updated

 

これで、証明書が失効する。

次に、クライアント証明書失効リスト(CRL)を作成する。これも認証局の作業。

デフォルトでは30日が失効リスト作成サイクルになっている。CRLは30日を経過すると無効になり、有効な証明書も「判断できないから接続させない」となる。実際にはそんなに頻繁に発行しないであろうこと、失効させる場合にはすぐに反映させる必要があること、を考慮すれば30日という設定ではなく、3650日(10年)でも良いのではないか?と思ったりしたのでその設定をする。

/etc/ssl/openssl.cnf
・・・
[ CA_default ]
・・・
default_crl_days= 3650
・・・

 

次に /etc/ssh/hogeCA/crlnumber があるか確認する。なければ作る。

$ sudo sh -c "echo '00' > /etc/ssl/hogeCA/crlnumber"

 

準備ができたので、CRLを作成する。

$ sudo openssl ca -gencrl -out /etc/ssl/hogeCA/crl/hogeserver.crl
Using configuration from /etc/ssl/openssl-client.cnf
Enter pass phrase for /etc/ssl/hogeCA/private/cakey.pem:[CA秘密鍵のパスワード]

 

中身を確認してみる。

$ openssl crl -text -noout -in hogeserver.crl
Certificate Revocation List (CRL):
        Version 2 (0x1)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: /C=JA/ST=Tokyo/O=hogeserver/CN=hogeserver.hogeddns.jp/emailAddress=webmaster@hogeserver.hogeddns.jp
        Last Update: Jun  3 06:06:36 2017 GMT
        Next Update: Jun  1 06:06:36 2027 GMT
        CRL extensions:
            X509v3 CRL Number:
                1
Revoked Certificates:
    Serial Number: XXXXXXXXXXXXXD14
        Revocation Date: May  2 13:51:55 2017 GMT
    Serial Number: XXXXXXXXXXXXXD15
        Revocation Date: May  2 14:27:07 2017 GMT
    Serial Number: XXXXXXXXXXXXXD16
        Revocation Date: May  2 14:51:32 2017 GMT
    Serial Number: XXXXXXXXXXXXXD1A
        Revocation Date: Jun 3 05:24:06 2017 GMT
    Signature Algorithm: sha256WithRSAEncryption
         XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:
           ・
           ・
           ・
         XX:XX:XX:XX

 

できあがったファイルを各サーバーに配布。

サービスを提供するサーバーはCRLを配置して、Apachに適用する。

/etc/apache2/sites-enabled/alfresco.conf
#
# Alfresco SSL公開設定
#
<VirtualHost *:443>

        ServerAdmin  webmaster@hogeserver.hogeddns.jp
        ServerName   docshare.hogeserver.hogeddns.jp
        DocumentRoot /var/www/html

        ErrorLog  ${APACHE_LOG_DIR}/ssl-error.log
        CustomLog ${APACHE_LOG_DIR}/ssl-access.log combined

        SSLEngine on
        SSLCertificateFile    /etc/ssl/private/docshare.crt
        SSLCertificateKeyFile /etc/ssl/private/docshare.key

        SSLCACertificateFile /etc/ssl/private/hogeserver.hogeddns.jp.crt
        SSLCARevocationFile  /etc/ssl/private/hogeserver.hogeddns.jp.crl

        SSLVerifyClient optional
        SSLVerifyDepth  1

        SSLCARevocationCheck chain

        <Location /share>
                ProxyPass ajp://localhost:18009/share
                SSLRequire ( %{SSL_CLIENT_S_DN_O} in {"hogeserver"} ) \
                        or ( %{REMOTE_ADDR} =~ m/^192\.168\.NNN\.[0-9]+$/ )
        </Location>

        <Location /alfresco>
                ProxyPass ajp://localhost:18009/alfresco
                SSLRequire ( %{SSL_CLIENT_S_DN_O} in {"hogeserver"} ) \
                        or ( %{REMOTE_ADDR} =~ m/^192\.168\.NNN\.[0-9]+$/ )
        </Location>

        RewriteEngine On
        RewriteCond %{HTTPS} off
        RewriteRule ^alfresco/(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

</VirtualHost>

※これは初回のみ行えばOK。赤文字が追記部分で、CRLが使いたくなったら追加すれば良い、ということになる。そして、配布されたCRLは /etc/ssl/privateに配置している。

CRLを有効化するためにリロードする。

$ sudo service apache2 reload

 

 

その他

超頭をすっきりさせてくれた記事。
Alfresco SSL with Apache Proxy Server

本家のSLL設定説明。
Configuring SSL for a production environment

クライアント認証をそのまま外部認証につなげればイイのかもしれない。
Setting Alfresco SSO with client certificates
Configuring external authentication

クライアント設定でとても役に立った。
Alfresco Mobile for Android : Advanced Setup Guide

 

所感

今回、色々と設定をしながら面倒だったのは、ブラウザがキャッシュをしてしまうために、確認が確認にならないケースが多々あったこと。最後は tail -f ssl-error.log でログをずっと表示させながら動作確認したのだった。Apacheの動作が不安定…そんなはずないなー、と悩んでいることがアホらしい。

最終的には、これでいける!という所まで来たので、これからゆっくりとAlfrescoを使って楽しんでいこうと思う。

お気軽にどうぞ ~ 投稿に関するご意見・感想・他

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です