有効な証明書なのにcertificate has expiredになる件

サーバー上のPHPからcURLで外部APIを叩いた時に起こりました。
HTTPのテスト系APIで動作確認した後、HTTPSの本番系APIに切り替えると以下のエラーが返ってきました。

curl: (60) The certificate issuer's certificate has expired.  Check your system date and time.

クライアントのWebブラウザから、HTTPSの本番系に正常に接続できていることは確認済みです。
つまりSSL証明書が有効なので、certificate has expired=証明書の有効期限切れではないことは明白です。

試しにサーバー内に入って直接curlコマンドを打ってみます。

[vagrant@dev ~]$ curl https://something.com/
curl: (60) The certificate issuer's certificate has expired.  Check your system date and time.
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

ここで確認しなければならないことは「サーバーの時刻が同期されているか?」です。
(エラーメッセージにも書いてあります)

当たり前ですが、証明書の有効期限切れの判定にはシステム時刻を使用しています。
そのためサーバーの時刻を合わせる必要があります。

NTPが設定されているかどうかを確認し、されていなければ設定しましょう。

しかし、私のパターンではサーバーの時刻も合っていました。

目次

ルートCA証明書が失効している

以下のコマンドでca-certificatesパッケージを更新することで解決できました。

sudo yum update ca-certificates

更新前

[vagrant@dev ~]$ yum list installed | grep ca-certificates
Repodata is over 2 weeks old. Install yum-cron? Or run: yum makecache fast
ca-certificates.noarch                2015.2.4-70.0.el7_1            @updates  

更新後

[vagrant@dev ~]$ yum list installed | grep ca-certificates
ca-certificates.noarch                2021.2.50-72.el7_9             @updates  

2015年のパッケージから更新されていなかったようですね。

ちなみにyum updateすら証明書エラーになってしまう場合は、別な手段でca-certificatesパッケージを取得してインストールする必要があります。

なぜ解決したのか?

時は遡ること2021年9月30日。
この日にLet’s Encryptが使用しているDST Root CA X3という証明書の有効期限が切れました。

ZDNET Japan
Let's EncryptのルートCA証明書期限切れ、多数のサイトで問題発生 HTTPSに使用する証明書を無料で発行しているLet's Encryptが使用しているルート証明書が期限切れになったことで、多くのサイトで問題が発生している。

この影響で古い環境では証明書エラーが発生してしまいます。
Let’s EncryptのルートCA証明書は新しい証明書に更新されていますが、それに対応した証明書を端末にインストールしておかなければ、端末は新しい証明書を認識できません。

こんなルート証明書知らん!

と認識してしまうのですね。

そしてAPIのSSL証明書も、このLet’s Encryptを使っていました。

クライアントであれば、Windows UpdateなどのOSアップデートにあたる更新を行っていれば問題ありません。
サーバーでも同じで、今回のケースでもyum updateを行っていれば問題は起きていませんでした。

しかし長らくyum updateしていなかったため、ルートCA証明書が入っているca-certificatesパッケージが古いままになっていたのです。

余談

PHPプログラムにはJavaScriptのXMLHttpRequestでアクセスしており、エラーが発生した場合はcURLのステータスコードをJSONで返すようにしていました。

そして返ってきたcURLのステータスコードはなぜか0。
お前誰やねん。100番台のステータスコードすら見たことないのに

ちょっとハマりかけましたが、cURLのエラーメッセージを吐き出すようにしたら冒頭のメッセージが出現。
状況的にルートCA証明書絡みなのかなぁと思ったらビンゴでした。

  • URLをコピーしました!
目次