会社で作る認証局

社内システムとして文書共有サーバーを建てようとしているのだが、SSLを要求することになる見込み。適当にオレオレ証明書を作ってもアクセスできないブラウザが現れたこともあって、社内システムなのだからむしろ他から認証して貰う必要などなく、自分でカッチリした認証局を作れば良い、と考えてやり方を学習してみた。



考え方としては、

  • 社としての認証局を作る。
  • 認証局の証明書を作る。→ DER形式
  • この証明書を会社の皆さんに配り、ルート証明書として登録してもらう。
  • 他のシステムの証明書には、この認証局を使って署名する。

ということになる模様。

将来的にはクライアント認証なんてのもやってもいいかも。
そして、最近のGoogle Chrome Ver.58で証明書エラーが出る問題にも対応しよう。

これ、ちゃんとやれば、自宅のESXiで出続けている証明書エラーも改善できるなー。


登場する言葉

  • 認証局(CA/Certificate Authority)
    今回は社内で利用する自己認証局を作ろうとしている。
  • CRL(Certificate Revocation List)
    エンドユーザーの証明書失効リスト。

登場する拡張子

  • der(Distinguished Encoding Rules)
    ASN.1データ構造をバイナリ形式で符号化したファイル。今回の記事では、認証局証明書の件で登場する。DER符号化はBERを一部制限したもの。
  • pem(Privacy-enhanced Electronic Mail)
    ASN.1データ構造をBase64で符号化したファイル。中身はcsrだったり、keyだったりと様々。
  • csr(Certificate Signing Request)
    証明書への署名要求ファイル。
  • crt
    証明書。
  • key
    秘密鍵。

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

  • 認証局構築
    ・事前設定
    ・認証局構築
    ・できあがるファイル達
  • 認証局としての仕事
    ・認証局証明書(CA証明書)の発行
    ・社内システムの証明書署名要求への署名
    ・証明書の失効
    ・他の認証局証明書への署名
  • サーバー管理者としての仕事
  • その他
    ・各種ファイルの中身の確認

…思った以上に長い道のりに。


■認証局構築

□事前設定

事前に以下を修正しておく。

認証局構築スクリプト

/usr/lib/ssl/misc/CA.sh
if [ -z "$DAYS" ] ; then DAYS="-days 3650" ; fi # 10 year
CADAYS="-days 10950"    # 30 years ←CAを30年(事実上の無期限)

if [ -z "$CATOP" ] ; then CATOP=/etc/ssl/hogeCA ; fi

設定ファイル

/etc/ssl/openssl.cnf
[ CA_default ]
dir             = /etc/ssl/hogeCA
default_days    = 3650 ←10年使えるようにする(事実上の無期限か)

[ req ]
x509_extensions         = v3_ca ←追加

[ req_distinguished_name ]
countryName_default           = JA
stateOrProvinceName_default   = Tokyo
0.organizationName_default    = Hoge

[ v3_ca ]
subjectAltName=DNS:hogeserver.hogeddns.jp ←追加

※DNS:abc.jp,DNS:*.abc.jp;IP:192.168.nnn.nnnといった設定が可能。

□認証局構築

事前設定を済ませたら、コマンドを投入していく。

$ cd /usr/lib/ssl/misc
$ sudo ./CA.sh -newca
CA certificate filename (or enter to create)[Enter]

Making CA certificate ...
Generating a 2048 bit RSA private key
.........................................+++
......................................+++
writing new private key to './hogeCA/private/./cakey.pem'
Enter PEM pass phrase:[Pass phrase][Enter]
Verifying - Enter PEM pass phrase:[Pass phrase][Enter]
-----
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) [JP]:[Enter]
State or Province Name (full name) [Tokyo]:[Enter]
Locality Name (eg, city) []:Chiyoda[Enter]
Organization Name (eg, company) [Hoge]:[Enter]
Organizational Unit Name (eg, section) []:[Enter]
Common Name (e.g. server FQDN or YOUR name) []:hogeserver.hogeddns.jp[Enter]
Email Address []:webmaster@hogeserver.hogeddns.jp[Enter]

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:[Enter]
An optional company name []:[Enter]
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./hogeCA/private/./cakey.pem:[上で指定したPass phrase][Enter]

Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 15403724308045004582 (0xd5c505a54f127f26)
        Validity
            Not Before: Apr 29 09:10:27 2017 GMT
            Not After : Apr 22 09:10:27 2047 GMT
        Subject:
            countryName               = JA
            stateOrProvinceName       = Tokyo
            organizationName          = Hoge
            commonName                = hogeserver.hogeddns.jp
            emailAddress              = webmaster@hogeserver.hogeddns.jp
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                9C:48:33:DE:37:B4:DB:57:9E:BC:94:25:C1:08:C6:FA:7F:21:06:16
            X509v3 Authority Key Identifier:
                keyid:9C:48:33:DE:37:B4:DB:57:9E:BC:94:25:C1:08:C6:FA:7F:21:06:16

            X509v3 Basic Constraints:
                CA:TRUE
            X509v3 Subject Alternative Name:
                DNS:hogeserver.hogeddns.jp ←これが出ていれば、ChromeでOK。
Certificate is to be certified until Apr 22 09:10:27 2047 GMT (10950 days)

Write out database with 1 new entries
Data Base Updated
hogeuser@hogeserver:/usr/lib/ssl/misc$

□できあがるファイル達

スクリプトを実行した結果、以下のディレクトリとファイルが作られた。

hogeCA
├ cacert.pem       認証局(CA)の証明書※公開鍵を含み、全ユーザーに配布。
├ careq.pem        他の認証局に署名を要求するためのファイル。
├ index.txt        証明書の有効/失効の履歴を保管。
├ index.txt.attr   index.txtの通番重複の可否設定。
├ index.txt.old    
├ serial           次の証明書の16進数シリアル番号。
├ certs/           発行された証明書が保管される場所。ファイル名はhash化される。
├ newcerts/        新しい署名入り証明書のコピーをが保管される場所。
├ crl/             発行された証明書失効リスト(CRL)が保管される場所。ファイル名はhash化される。
└ private/         
    └ cakey.pem    認証局(CA)の秘密鍵※最重要、これがあればCA証明書複製可能。

最重要と思われる認証局の秘密鍵は簡単に読めないようにする。

$ sudo chmod 600 /etc/ssl/hogeCA/private/cakey.pem

■認証局としての仕事

□認証局証明書(CA証明書)の発行

まずは、全社標準として認証局証明書を発行。

$ sudo openssl x509 -inform PEM -in /etc/ssl/hogeCA/cacert.pem -outform DER -out /etc/ssl/hogeCA/private/hogeserver.hogeddns.jp.der

もしくは、/etc/ssl/hogeCA/cacert.pemから

-----BEGIN CERTIFICATE-----
記号群
-----END CERTIFICATE-----

をコピーして、/etc/ssl/hogeCA/private/hogeserver.hogeddns.jp.crt として保存する。

できあがった 証明書(DER or CRT)を共有フォルダやメール等で配信し、「信頼されたルート証明機関」として登録してもらう。
Windows10で「自動的に証明書ストアを選択する」を選ぶと、「中間証明機関」に入ってしまうので、丁寧な手順書が必要になる見込み。

□社内システムの証明書署名要求への署名

社内システムが独自に発行する証明書に署名する。
CA.shスクリプトを利用するが、固定のファイル名が前提になるため、以下のようなディレクトリ構成で管理する予感。

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

事前準備として、受け取った要求をnewreq.pemとして配置。
そして、Subject Alternative Nameをチェックする。

$ sudo openssl req -text -noout -in newreq.pem
<省略>
X509v3 extensions:
  X509v3 Subject Alternative Name:
    DNS:esxi.hogeserver.hogeddns.jp, DNS:esxi, IP Address:192.168.nnn.nnn
<省略>

都度、openssl.cnfに以下のような必要なアクセスURLを追記する。

/etc/ssl/openssl.cnf
[ usr_cert ]
subjectAltName=@user_cert_altname ←追加

[ user_cert_altname ] ←セクションごと追加
DNS.1=esxi.hogeserver.hogeddns.jp
DNS.2=esxi
IP.1=192.168.nnn.nnn

※設定してあげないとGoogle Chrome Ver.58 でエラーが発生するから。

設定を終えたら、スクリプトで署名する。

$ sudo /usr/lib/ssl/misc/CA.sh -sign
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/hogeCA/private/cakey.pem:[Pass phrase][Enter]
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: nnnnnnnnnnnnnnnnnnnn (0xHHHHHHHHHHHHHHHH)
        Validity
            Not Before: Apr 29 23:39:11 2017 GMT
            Not After : Apr 29 23:39:11 2018 GMT
        Subject:
            countryName               = US
            stateOrProvinceName       = California
            localityName              = Palo Alto
            organizationName          = VMware, Inc
            organizationalUnitName    = VMware ESX Server Default Certificate
            commonName                = esxi.hogeserver.hogeddns.jp
            emailAddress              = hogehoge@vmware.com
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN
            X509v3 Authority Key Identifier:
                keyid:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN:NN

            X509v3 Subject Alternative Name:
                DNS:esxi.hogeserver.hogeddns.jp, DNS:esxi, IP Address:192.168.nnn.nnn
Certificate is to be certified until Apr 27 23:48:04 2027 GMT (3650 days)
Sign the certificate? [y/n]:y[Enter]


1 out of 1 certificate requests certified, commit? [y/n]y[Enter]
Write out database with 1 new entries
Data Base Updated
Certificate:
    Data:
・
・
・
Signed certificate is in newcert.pem

できあがったnewcert.pemから

-----BEGIN CERTIFICATE-----
記号群
-----END CERTIFICATE-----

を切り取って、適切なファイル名.crt として要求側に返送する。

□証明書の失効

発行済の証明書を失効させるには以下を行う。

$ sudo openssl ca -revoke 失効させる証明書.pem
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/hogeCA/private/cakey.pem:[Pass phrase][Enter]
Revoking Certificate 失効させる証明書.
Data Base Updated

※動作確認のため同じ証明書を繰り返し認証しようとして以下のエラーが発生した。

Sign the certificate? [y/n]:y[Enter]
failed to update database
TXT_DB error number 2
Signed certificate is in newcert.pem

元の証明書を失効させることで、新たに発行できた。

だが、この失効情報をどのように配布するのか。この点はこれから学習。←2017/05/02

□他の認証局証明書への署名

他拠点のシステムまで管理しきれないので、各拠点に責任を持って認証局を立ててもらう…ということかと思う。やり方だけ調べてみて、必要になったら実施。

拠点で認証局を立ててもらい、CA.sh -newreq で作成したリクエストから

-----BEGIN CERTIFICATE REQUEST-----
記号
-----END CERTIFICATE REQUEST-----

の部分を送ってもらう。

これを newreq.pem として保存して以下を実行。←2017/05/02追記

$ sudo /usr/lib/ssl/misc/CA.sh -signCA 要求元CA.csr←訂正2017/05/02
$ sudo /usr/lib/ssl/misc/CA.sh -signCA

これで中間CAに署名できる(ハズ)

できあがった newcert.pem から

-----BEGIN CERTIFICATE-----
記号
-----END CERTIFICATE-----

を yourca.crt とでもして返送すればOK。

と、思ったのだが、実際には中間CAで署名した証明書は役に立たなかった。もう少し勉強が必要らしい…←2017/05/02追記

■サーバー管理者としての仕事

証明書が必要な社内サーバーを立ち上げたら、サーバー独自に秘密鍵とサーバー証明書署名要求を作成する。作成は以下で行う(ことにする、明確に決まっていなさそう)。rootでの作業になる。

/etc/ssl/private

※認証局と同じサーバーに同居していても、署名を受ける側としてここで作業。

まず、openssl.cnfにサーバーのURLを入れておく。

[ req ]
req_extensions = v3_req ← コメント化されているのを有効化

[ v3_req ]
subjectAltName=@v3_req_altname ←追加

[ v3_req_altname ] ←セクションごと追加
DNS.1=docshare.hogeserver.hogeddns.jp
IP.1=192.167.NNN.NNN

秘密鍵と証明書署名要求を生成する。

# openssl req -new -keyout docshare_key.pem -out docshare_csr.pem
Generating a 2048 bit RSA private key
..................................................................+++
.....................+++
writing new private key to 'docshare_key.pem'
Enter PEM pass phrase:(このサーバーとしてのパスフレーズ)[Enter]
Verifying - Enter PEM pass phrase:(〃)[Enter]
-----
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]:[Enter]
State or Province Name (full name) [Tokyo]:[Enter]
Locality Name (eg, city) []:Chiyoda[Enter]
Organization Name (eg, company) [Hoge]:[Enter]
Organizational Unit Name (eg, section) []:[Enter]
Common Name (e.g. server FQDN or YOUR name) []:docshare.hogeserver.hogeddns.jp[Enter]
Email Address []:webmaster@hogeserver.hogeddns.jp[Enter]

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:(何か入れてもいいみたい)[Enter]
An optional company name []:[Enter]
hogeuser:/etc/ssl/private#

※challenge passwordには何も入れなくてもOK。

何かと面倒らしいので、鍵にRSA鍵も入れ込む。

# openssl rsa -in docshare_key.pem -out docshare.key
Enter pass phrase for docshare_key.pem:(このサーバーとしてのパスフレーズ)[Enter]
writing RSA key

そして、できあがった証明書署名要求(上の例ではdocshare_csr.pem)を、認証局に送る。
認証局は、上で書いた方法で署名して証明書を返送(docshare.crt的な名前)してくるので、適切な場所に配置する。
Apacheでcrtとkeyをセットで指定して暗号化通信ができるようになる。2017/12/30更新

■その他

□各種ファイルの中身の確認

$ openssl req -text -noout -in リクエストファイル

$ openssl x509 -text -noout -in 確認したい証明書

■所感

とあるサービスを立ち上ながら、並行して認証局運営一連の事柄を学習するのはかなり厳しい。
今回は他のメンバーが立ち上げるサービスでSSLを要求するらしいので、側面からのサポートとして調べてみたが、ボリューム満点。とりあえず目先の作業だけでもこれで、とまとめてみた。基礎知識なのかもしれないが、それなりに大変だ…。

あと、Google Chrome Ver.58の問題で色々と学習してみたが、この手順を見ても結構無理のある変更だったように思われる。
いろいろ調べてみた(わからなかっただけかもしれない)。だけど、X509v3 Subject Alternative Nameはマルチドメインへの対応とかで使われることがある程度で、opensslで署名するときに「引き継ぎ」みたいのできないし、コピーするにしてもemailからのコピーしか書いてないし。上で書いたような署名時の手作業はミスを生み出すよなー、これはかなり酷いのかも、と思ったり。

ChromeやAndroidから別のものに移行する日が来たのかもしれない…。

■参考サイト

諸先輩が既に色々な形で情報を出してくれていたので、組み合わせれば行ける!ので、会社で使うところだけを抜き出してまとめた格好になった。

Chrome58で、HTTPSの自己証明書が NET::ERR_CERT_COMMON_NAME_INVALID になる場合の対応
これがわかったことから、今回の記事をまとめようという気になった。常用しているのはChromeだったし、それだと構築したシステムにアクセスできなくなるし。

CA 構築のための OpenSSL の設定
CA.shで作られたディレクトリたちが一体何のためにあるのか、わかりやすくまとめてあった。

プライベート認証局(CA)を構築して証明書の発行を行なう
スクリプト実行の実例が載っていたので参考になった。

独自SSLサーバ認証局(CA)作成とサーバ証明書発行
RSA鍵、証明書のファイルフォーマットについて
この方々は色々と正確な情報を正確な日本語で提供してくれる。検索してQiitaの文字が出てくるとラッキー。拡張子とか、CAとしての振る舞いが分かった。

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

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