エラーメッセージ
The remote certificate is invalid because of errors in the certificate chain: NotTimeValid
HttpClient は、これを「The SSL connection could not be established, see inner exception.」の内部例外として報告します。複数のフラグがまとめて表示されることもあります(例:「NotTimeValid, UntrustedRoot」)。
.NET SslStream / HttpClient — X509ChainStatusFlags.NotTimeValid
このエラーの意味
.NET が構築したチェーン内のいずれかの証明書が、このマシンの時計で見て有効期間外です。つまり、期限切れか、まだ有効ではありません。NotTimeValid はどの証明書かを示しませんが、検証コールバックで受け取るチェーン要素を見ればわかります。ルートと名前には問題がありませんでした。問題があれば、ほかのフラグも併せて表示されるはずです。
発生する理由
サーバーの証明書(または中間証明書)が期限切れ
よくある更新が行われなかったか、更新した証明書がバインドされていません(IIS のバインド、Kestrel の設定、Azure/Key Vault の参照、ロードバランサー)。
時計が遅れているクライアントでの発行直後の証明書
ときどき「現在」から有効になる証明書は、時計が数分遅れているマシンでは検証に失敗します。
クライアントの時計が間違っている
ときどきスナップショットから復元した VM、NTP を使っていないデバイス、時計がずれていくホスト上のコンテナーなどが該当します。
修正方法
- 1.
返される証明書の日付を確認する
notBefore と notAfter を現在の UTC 時刻と比較してください。
bash echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -subject -startdate -enddate - 2.
失敗しているチェーン要素をログに記録する
ChainElementStatus をログに記録し、既定の判定をそのまま返す検証コールバックを使えば、検証を弱めることなく、どの証明書が有効期間外なのかを確認できます。
csharp // Log which certificate failed and why, without accepting it var handler = new HttpClientHandler { ServerCertificateCustomValidationCallback = (msg, cert, chain, errors) => { foreach (var element in chain!.ChainElements) foreach (var status in element.ChainElementStatus) Console.WriteLine($"{element.Certificate.Subject}: {status.Status} {element.Certificate.NotAfter:u}"); return errors == System.Net.Security.SslPolicyErrors.None; }, }; - 3.
更新して再バインドする
証明書を更新し、その証明書を返しているすべてのバインドを新しい証明書に差し替えてください。
bash sudo certbot renew && sudo systemctl reload nginx # or renew in your CA / key vault and redeploy