CloudFront用に証明書をインポートするときは鍵長に注意しよう 〜ZeroSSLでデフォルトで作成される鍵を例にして〜

はじめに

清水です。先日、CloudFront用にAWS Certificate Manager (ACM) への証明書をインポート、CloudFrontディストリビューションに設定する機会がありました。証明書をACMで発行はせず、外部で発行した証明書をACMにインポートするパターンですね。検証用途でしたので証明書の発行にはLet's EncryptとZeroSSLを使用したのですが、条件によってはACMへのインポートは成功しても、CloudFrontディストリビューションに設定する際にエラーとなってしまい設定ができない、ということがありました。確認してみると、ZeroSSLで作成した秘密鍵、公開鍵のペアが4,096bitの鍵長であったため、ACMへのインポートはできても、CloudFrontディストリビューションへの適用ができなかった、ということがわかりました。(CloudFrontに設定できる証明書のパブリックキーのサイズは2019/04/30時点で1,024bitか2,048bitのみ。)本エントリではどのようなパターンで引っかかったのか、またどのように対応したかを備忘録がてらまとめてみたいと思います。

ZeroSSLで作成されるデフォルトの鍵をCloudFrontに設定しようとしてエラーとなったパターン

Let's EncryptとZeroSSLを使った証明書の発行

まずはZeroSSLで作成されるデフォルトの鍵を使った証明書をACMにインポートし、CloudFrontに設定しようとしてエラーとなったパターンです。Let's EncryptとZeroSSLを使った証明書の発行については、以下のトランの記事を参考にしました。

Free SSL Certificate Wizard and other SSL Tools @ ZeroSSLから証明書作成ウィザードを開始します。

証明書が必要なドメインを入力、verificationはDNSを選択します。ZeroSSL TOSとLet's Encrypt SAにAcceptして、[NEXT]で進みます。

CSRが作成されるので、ダウンロードして保存しておきます。[NEXT]で進みます。

Let's Encryptの一時アカウントが作成されます。左側に表示されている秘密鍵もダウンロードして保存します。[NEXT]で進みます。

認証情報が表示されますので、指定の通りにDNSレコードを追加します。

レコード追加後、[NEXT]で進むと認証が実行されます。(DNSレコード登録反映まで、少々時間を要しました。)

認証完了後、証明書が発行されます。BEGIN CERTIFICATEで始まるほうが証明書一式、BEGIN RSA PRIVATE KEYで始まるものが秘密鍵となりますね。これらを保存しておいます。

ZeroSSLで発行した証明書をACMへインポート

続いて、ZeroSSLで発行した証明書をACMへインポートします。マネジメントコンソールからCertificate Managerのページへ進み、[Import a certificate]でインポートします。この証明書はCloudFrontディストリビューションに適用するものなので、US.East(N.Virginia, us-east-1)リージョンで作業をする点に注意しましょう。

先ほどのZeroSSLでダウンロードしたファイルのうち、domain certificateの前半部分(1つ目のBEGIN CERTIFICATEからEND CERTIFICATEまで)がCertificate body、後半部分(2つ目のBEGIN CERTIFICATEからEND CERTIFICATEまで)がCertificate chainに該当します。またdomain keyがCertificate private keyになります。それぞれコピペして入力します。

特段エラーなどは発生せず、ACMにインポートすることができました。

CloudFrontディストリビューションに設定しようとしてみる

ACMにインポートできたので、CloudFrontディストリビューションに設定してみます。マネジメントコンソールでSSL CertificateでCustom SSL Certificateを選択、証明書を選択しようとしますが、一覧に表示されません。

ならば…、とACMでインポートした証明書に割り当てられているID(Identifier、今回なら74213で始まっているもの)を直接入力してみます。

が、[Yes, Edit]しようとすると下記の通りエラーが表示されてしまいます。

CloudFrontに設定できる証明書の要件を確認してみる

ACMにインポートした証明書がCloudFrontディストリビューションに設定できず、手詰まりとなってしまったため、Amazon CloudFront開発者ガイドでCloudFrontに設定できる証明書の要件を確認してみました。

いくつか要件はあるのですが、結果として今回該当したのは「パブリックキーのサイズ」つまり鍵の長さです。opensslコマンドで確認してみると4,096 bitであることがわかりました。

 $ openssl x509 -text -noout -in ./www.cft.mydomain.net.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            03:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3
        Validity
            Not Before: Apr 30 09:52:42 2019 GMT
            Not After : Jul 29 09:52:42 2019 GMT
        Subject: CN=www.cft.mydomain.net
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (4096 bit)
                Modulus:
    <以下略>

$ openssl rsa -text -noout -in ./www.cft.mydomain.net.key
Private-Key: (4096 bit)
modulus:
    <以下略>

先ほどのCloudFront開発者ガイド、「パブリックキーのサイズ」の箇所には以下のように記載があります。(2019/04/30現在の内容となります。)

AWS Certificate Manager (ACM) への証明書のインポート: パブリックキーの長さは 1,024 ビットまたは 2,048 ビットであることが必要です。ACM ではより大規模なキーがサポートされていますが、CloudFront で使用する証明書の制限は 2048 ビットです。

ということで、ACMへインポートした証明書をCloudFrontに設定する場合は、4,096 bitの鍵長のものは使用できず、最大でも2,048 bitの鍵長であることが確認できました。

なお、ACM自体は最大で4,096bit RSAキーがインポートできる、とのことです。そのため、4,096bit長の鍵については、証明書ストアとしてのACMでは対応しているが、CluodFrontでは(現時点では)対応していない、と認識しています。

ZeroSSLにCSRを入力して指定した鍵長で証明書を作成しCloudFrontに設定ができたパターン

ACMにインポートした証明書をCloudFrontディストリビューションに設定しようとしたとき、エラーが発生し設定できなかった原因が4,096bitの鍵長であることが確認できました。では上記のLet's EncryptとZeroSSLを使った証明書を使用する場合、鍵長を変更するにはどうしたら良いでしょうか。今回は、ローカル環境で2,048bitの秘密鍵を作成、ここからCSRを作成しこのCSRを用いてZeroSSLで証明書を発行することで、2,048bitの鍵長で証明書が発行できました。手順をまとめておきます。

ローカル環境で秘密鍵ならびにCSRの作成

opensslコマンドを用いて秘密鍵、ならびにCSRを作成します。秘密鍵作成時には2,048bitを指定しましょう。

秘密鍵を作成します。

$ openssl genrsa 2048 > www.cft.mydomain.net.key
Generating RSA private key, 2048 bit long modulus
......................+++
.......................................................+++
e is 65537 (0x10001)

続いてCSRを作成します。

$ openssl req -new -key www.cft.mydomain.net.key -sha256 -out www.cft.mydomain.net.csr
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) []:
State or Province Name (full name) []:
Locality Name (eg, city) []:
Organization Name (eg, company) []:
Organizational Unit Name (eg, section) []:
Common Name (eg, fully qualified host name) []:www.cft.mydomain.net
Email Address []:

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

CSRを指定してZeroSSLを使って証明書を発行する

続いてZeroSSLで証明書の発行です。先ほどと同じFree SSL Certificate Wizard and other SSL Tools @ ZeroSSLのウィザードから証明書発行を進めていきますが、ドメインの入力ではなく、ローカル環境で発行したCSRを右側に貼り付けます。

以降は(ZeroSSLによるCSR発行はありませんが)流れは同じです。Verificationを経て、証明書が発行されます。なお秘密鍵については(ZeroSSL側で保持していないこともありますので)ダウンロードはできません。

2,048bitの鍵長の証明書をACMへインポート

この2,048bitの鍵長の証明書をACMへインポートします。手順は先ほどと同様ですが、マネジメントコンソールからUS.EastリージョンのCertificate Managerのページへ進み、[Import a certificate]でインポートします。ZeroSSLでダウンロードしたファイルのうち、domain certificateの前半部分(1つ目のBEGIN CERTIFICATEからEND CERTIFICATEまで)をCertificate bodyに、後半部分(2つ目のBEGIN CERTIFICATEからEND CERTIFICATEまで)をCertificate chainに入力します。またローカル環境で作成した秘密鍵の内容をCertificate private keyに入力します。さらに、Review画面でPublic key infoから2,048bitであること(RSA-2048)を確認しておきましょう。

2,048bitの鍵長の証明書をCloudFrontディストリビューションに設定

ACMへインポートできたら、CloudFrontディストリビューションに設定します。先ほどの4,096bitの鍵長のときと異なり、Custom SSL Certificateの証明書一覧の箇所に表示されますので、こちらを選択し、[Yes, Edit]で反映、Deployが完了するのを待ちましょう。

まとめ

鍵長を確認せずに4,096bitの鍵長の証明書をACMにインポート、CloudFrontディストリビューションに設定しようとしたら証明書の要件に合致せずエラーとなってしまった点をまとめてみました。ふだんそこまで証明書の鍵長を気にすることがなかったため、引っかかりはしたけれど大変勉強になりました。CloudFrontに設定できる証明書の鍵長は1,024bitもしくは2,048bitであることを頭の片隅におき、また設定前には鍵長の確認をするようにしたいと思います。