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を使って楽しんでいこうと思う。