iOSデバイスにノーティフィケーションを送れなくなった
AppleへのTLS接続が確立できなくなった
2021年2月8日ごろから、HerokuアプリケーションからiOSデバイスへのノーティフィケーションの送信ができなくなっているようです。アプリケーションからAppleのエンドポイントへのTLS接続の過程でx509: certificate signed by unknown authority
といったエラーが記録されます。これは2月8日のスタックイメージの更新で、ca-certificates
パッケージが更新されたことによるもののようです。
実際、heroku-20スタックのアプリケーションのone-off dynoではAppleのエンドポイントのTLS証明書の検証ができなくなっていました。「unable to get local issuer certificate」というエラーメッセージが見られます。
$ heroku run ':| openssl s_client -connect api.push.apple.com:443 > /dev/null'
depth=1 CN = Apple IST CA 2 - G1, OU = Certification Authority, O = Apple Inc., C = US
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 CN = api.push.apple.com, OU = management:idms.group.533599, O = Apple Inc., ST = California, C = US
verify return:1
DONE
macOS (10.15.7 Catalina)では検証できました。
$ :| openssl s_client -connect api.push.apple.com:443 > /dev/null
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify return:1
depth=1 CN = Apple IST CA 2 - G1, OU = Certification Authority, O = Apple Inc., C = US
verify return:1
depth=0 CN = api.push.apple.com, OU = management:idms.group.533599, O = Apple Inc., ST = California, C = US
verify return:1
poll error
このルート証明書GeoTrust Global CA
はDebian Linuxのca-certificates
パッケージから2020年6月2日に取り除かれました。2021年2月5日ごろに再度追加されたようですが、パッケージを更新するだけでは信頼するルート証明書とはならないようです:
due to bug #743339, CA certificates added back in this version won't automatically be trusted again on upgrade. Affected users may need to reconfigure the package to restore the desired state.
とりあえずの対応
HerokuアプリケーションがGeoTrust Global CA
を信用するようにすることもできます。
下記の例では、https://www.geotrust.com/resources/root-certificates/ からルート証明書を取得して、openssl s_client
コマンドに-CAfile
オプションで指定します。
$ heroku run bash
~ $ curl -sO https://www.geotrust.com/resources/root_certificates/certificates/GeoTrust_Global_CA.pem
~ $ :| openssl s_client -CAfile GeoTrust_Global_CA.pem -connect api.push.apple.com:443 > /dev/null
depth=2 C = US, O = GeoTrust Inc., CN = GeoTrust Global CA
verify return:1
depth=1 CN = Apple IST CA 2 - G1, OU = Certification Authority, O = Apple Inc., C = US
verify return:1
depth=0 CN = api.push.apple.com, OU = management:idms.group.533599, O = Apple Inc., ST = California, C = US
verify return:1
DONE
アプリケーションから参照する場合には、ローカルで取得したルート証明書をアプリケーションのコードと一緒にレポジトリに登録し、そのルート証明書を参照するようにアプリケーションのコードを変更することになるでしょう。取得したルート証明書が正当なものであることを確認すると安全です。
Appleによる対応
Apple Push Notification service server certificate updateによると、エンドポイントの証明書は3月29日にルート認証局AAA Certificate Services
に認証されたものに更新されるようです。2月10日現在、このルート証明書はheroku-20スタックに提供されています。
$ heroku run 'openssl x509 -in /usr/share/ca-certificates/mozilla/Comodo_AAA_Services_root.crt -noout -fingerprint -issuer -enddate'
SHA1 Fingerprint=D1:EB:23:A4:6D:17:D6:8F:D9:25:64:C2:F1:F1:60:17:64:D8:E3:49
issuer=C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services
notAfter=Dec 31 23:59:59 2028 GMT
(4月9日追記)
再度、heroku-20スタックのアプリケーションのone-off dynoではAppleのエンドポイントのTLS証明書の検証ができるようになっていました。予告通り、ルート認証局AAA Certificate Services
に認証されたものに更新されたようです。
$ heroku run ':| openssl s_client -connect api.push.apple.com:443 > /dev/null'
depth=2 C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services
verify return:1
depth=1 CN = Apple Public Server RSA CA 12 - G1, O = Apple Inc., ST = California, C = US
verify return:1
depth=0 CN = api.push.apple.com, OU = management:idms.group.887777, O = Apple Inc., ST = California, C = US
verify return:1
DONE
どうしてこうなった
GeoTrustの証明局の信用は2017年ごろから落ちてました。確かにそんなことがあった気がする。この影響がDebian Linuxから提供されているパッケージまで波及してきたようです。
Discussion