🔏

iOSデバイスにノーティフィケーションを送れなくなった

2021/02/10に公開

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