Wednesday, February 10, 2016

Name Constraints を使った独自CAの運用手順

ウェブブラウザが新機能をHTTPSでしか有効にしないことが多くなってきたので、開発環境でもHTTPSを使いたい。でも、開発環境用にサーバ証明書を買うのは手間。Let's Encryptも運用がめんどくさいとか、社内からしかアクセスできないサーバへの証明書発行が難しいとかいろいろあるし…ってそこでName Constraintsを使った独自CAですよ奥さん。

Name Constraints が何であるかについては、以前オレオレ認証局の適切な運用とName Constraintsに書いたとおり。

本稿では、Name Constraintsを使うCAの運用手順を説明する。

1. CA鍵と証明書の作成

1.1. CAの秘密鍵を作成
% openssl genrsa -out ca.key 2048

1.2. openssl.cnfにCA証明書に設定する属性を指定するセクションを追記
[private_ca]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints=critical,CA:true
nameConstraints=critical,permitted;DNS:.example.com
注:nameConstraintsの項がCAが証明書を発行できる対象のドメインを指定。この例では.example.com。

1.3. CA証明書の作成
% openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
  -extensions private_ca

2. 証明書管理用ディレクトリを作成
% mkdir -p demoCA/newcerts
% touch demoCA/index.txt
% echo 00 > demoCA/serial
注:ディレクトリ名(demoCA)はopenssl.cnfの設定で変更可能。

3. 証明書発行要求を受け取って証明書を発行
% openssl ca -keyfile ca.key -cert ca.crt \
  -extensions usr_cert -policy policy_anything -days 365 \
  -md sha256 -in foo.example.com.csr -out foo.example.com.crt

以上です。

難点としては、SafariおよびOSXで動作するChromeではこのルート証明書で署名されたサーバ証明書を正当なものとして認識してくれないところ(手動でサーバ証明書を登録すれば使えるはず)。他のウェブブラウザ+モダンなOSなら問題ないはず。

5 comments:

  1. 証明書を認証する側が古い OpenSSL (少なくとも CentOS 7 が該当)だと name constraints は「DNS:example.com」でないと駄目でした。「DNS:.example.com」 だと CN=www.example.com な証明書を permitted subtree violation で拒否します。

    RFC 5280 の記述は曖昧ですが、DNS の場合はこれ(先頭のドットなし)でサブドメインも含めマッチするように読めます。

    なお、CentOS 7 の Mozilla NSS はどちらでも大丈夫でした。

    OpenSSL - Dev - nameConstraints : leading "." in permission list items
    http://openssl.6102.n7.nabble.com/nameConstraints-leading-quot-quot-in-permission-list-items-td52739.html
    Properly handle RFC5280 DNS Name Constraints that start with a dot as in mozilla::pkix by apapagiannakis · Pull Request #111 · openssl/openssl
    https://github.com/openssl/openssl/pull/111

    ReplyDelete
    Replies
    1. コメントありがとうございます。

      おっしゃるとおり、RFCの記述だとdNSNameの場合はドット不要ですね。ドメイン名制限の目的が、「そのドメイン配下に属するホスト名についてのみ証明書発行を許可する」という点にあることを考えると、先行するドットが不要という仕様は合理的かと思いました(メールアドレスの場合と異なるのは混乱を招きそうですが)。

      というわけで、ドットをつけないのが正しいと考えるべきなのかなと思うのですが、いかがでしょう? つけたものも name constraints に含めるべき理由ってありますでしょうか。

      Delete
  2. ドットなしでサブドメインも含むのが正しい、に同意します。ただし、古い OpenSSL とは逆にドットありでないと拒否する実装が存在するかもしれないので、両方とも含めておくのが無難かもしれません。

    RFC 的には、ドットなしでサブドメインにもマッチする仕様は合理性を感じませんね、個人的には。完全一致する名前を許可あるいは拒否したい場合も考えられなくはないですし。

    ReplyDelete