2020/10/26までにAzure Database for MySQL/MariaDBのサーバ証明書を更新しないと死ぬ


`Azure Database for MySQL/MariaDB`を使用している全サービスについて、2020/10/26以降データベースに接続できなくなる可能性があります。
自分の環境を確認し、必要であればサーバ証明書を更新しましょう。

なお、以下はよくわかってないところを適当に解釈しているため、断言している部分にも誤りが含まれている可能性が多大にあります。
きっと誰かが訂正をプルリクしてくれるはず。


# TL;DR

`Azure Database for MySQL/MariaDB`のサーバ証明書のルート証明書が変更される。

## しないといけないこと

現在使っている`BaltimoreCyberTrustRoot.crt.pem`を、`BaltimoreCyberTrustRoot.crt.pem`と`DigiCertGlobalRootG2.crt.pem`をくっつけたファイルに差し替える。

## しないといけない場所

`Azure Database for MySQL/MariaDB`に手動でSSL接続しているクライアント側全て。
`Azure Database for MySQL/MariaDB`側ではない。


# 公式ドキュメント

[Azure Database for MySQL のルート CA の変更について](https://docs.microsoft.com/ja-jp/azure/mysql/concepts-certificate-rotation)
[Azure Database for MariaDB のルート CA の変更について](https://docs.microsoft.com/ja-jp/azure/mariadb/concepts-certificate-rotation)

それぞれMySQLとMariaDB向けですが、中身はだいたい同じです。

記事を読むとわかりますが、何言ってるかわかりません。
私がわかっていないからというものもちろんありますが、それを抜きにしても文章からわかりにくさが溢れています。


# Azure Databaseの確認

まずAzure管理画面から、`Azure Database`の『接続のセキュリティ』タブを開きます。
『SSL接続を強制する』にチェックが入っている場合は、以下の作業を行う必要があります。
チェックが入っていない場合は、SSL接続と非SSL接続の、両方の方法で接続することができます。
従ってその場合はクライアント側がどうなっているか調べて、SSL接続しているのであれば以下の作業を行う必要があります。

あれ？結局ここ調べる意味なし？


# クライアントの確認

ここはクライアントの実装によって様々です。

接続に`Azure Functions`の入出力バインドなどを使っている場合は、特に対応する必要はありません。
Azure側が自動的にアプデしてくれるからです。

VMや普通のサーバから接続している場合、もしくはFunctionsでも直接`new PDO`とか`mysql.connector.connect()`とかやっている場合は、調査を行いましょう。
接続まわりのソースに`PDO::MYSQL_ATTR_SSL_CA`とか`ssl_ca=xx`とか書いてあったら、更新作業を行う必要があります。


## する必要があるかどうかの厳密な判定

これは公式ドキュメントに書いてあるのですが、接続文字列の`sslmode`に`verify-ca`もしくは`verify-full`が入っていたら必要、となっています。
それ以外の文字、もしくは`sslmode`がない場合は不要です。

## sslmodeについて

サーバが渡してきたサーバ証明書を、クライアントがどこまで厳しくチェックするのかという設定です。
何故か詳しい解説が[PostgreSQLのドキュメント](https://www.postgresql.jp/document/8.4/html/libpq-connect.html)くらいしか見当たらないんだけど。

`sslmode`が無ければ、そもそもSSLではないので無関係。
`sslmode`があっても、値が`allow`や`prefer`なら非SSL接続も行うため、SSL接続に失敗しても問題なし。
値が`require`であれば、SSL接続はするものの、クライアントはサーバ証明書をチェックしないので、証明書が正しくないことに気付かずSSL接続できるので問題なし。
値が`verify-ca`や`verify-full`であれば、証明書が使えないことを正確に判定してエラーを出すため接続できない。

ということになってはいるのですが、まあわかりにくいですよね。
従って、SSLであればとりあえず作業するって方向でよいのではないかと思います。


# 作業内容

既存の`BaltimoreCyberTrustRoot.crt.pem`に相当するファイルをテキストエディタで開いて、下に`DigiCertGlobalRootG2.crt.pem`の中身をペーストします。

これだけでOKです。
いやー証明書って1ファイルにまとめて書いてもいいんですね。

これによって、今まで使っていたBaltimoreCyberTrustRootが使えなくなっても、その後はDigiCertGlobalRootG2で認証するので大丈夫、ということになります。

## サンプル

<details><summary>これに差し替えるだけでOK。</summary><div>

```text
-----BEGIN CERTIFICATE-----
MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
MrY=
-----END CERTIFICATE-----
```

</div></details>

なお、Javaはこれではだめで、keytoolを使ってインポートする必要があるそうです。
よくわからないのでドキュメント読んでください。


# なんで使えなくなるの？

よく ~~調べてない~~ わからない。

SSL証明書は、証明書パスという仕組みで暗号化の安全性を保証しています。

Azure Databaseに使う証明書の安全性は、別の証明書Aが保証している。
証明書Aの安全性は、別の証明書Bが保証している。
証明書Bの安全性は、さらに別の証明書Cが保証している。
と繰り返していって、最終的にはルート証明書まで辿り着きます。
ルート証明書はブラウザやOSに最初から入っていて、無条件で安全であると見做されています。
従って、証明書パスにルート証明書が出てくれば、その証明書は安全であると判断するわけです。

Baltimore CyberTrust Rootもルート証明書のひとつです。
[携帯電話](https://www.nttdocomo.co.jp/service/developer/make/content/ssl/spec/)にすら入っているほど有名な証明書で、有効期限も2025年までなのでまだ余裕があります。
ブラウザやOSには入ってますが、しかしPHPやらPythonやらJavaやらの言語には入っていないので、ルート証明書の判定用としてサーバに置いておく必要があるわけですね。

期限が先といっても、秘密鍵が漏洩したなどの理由で期限を待たずに強制的に失効することはままあります。
しかし、今回はルート証明書そのものが失効するわけではなさそうです。
そんなだったらもっと騒ぎになってそうですからね。

従って今回は、Azure Databaseに使っている証明書からBaltimore CyberTrust Rootへの証明書パスのどこかにある中間CA証明書が失効するものだと思われます。
ちゃんと調べればそこらへんもわかるはずですが、面倒なのでスルー。
まあおそらくは[何かが漏れた](https://gigazine.net/news/20180304-private-keys-on-emails/)とか[認証局ごと信用を失った](https://www.itmedia.co.jp/enterprise/articles/1803/08/news066.html)とかだと思います。
証明書パスのどこかの証明書が失効すると、そこでパスが途切れてしまってルート証明書まで辿り着けなくなるので、その証明書は信用できない、となるわけです。

今回かわりに追加するDigiCert Global Root G2も同じくルート証明書で、こちらは2038年まで使えます。
同じルート証明書を使う証明書を発行すれば、差し替えも必要ないと思うのですが、何故ルート証明書まで変更するのかはよくわかりません。


# まとめ

`Azure Database`を使っている人は、速やかに確認しましょう。

まあ`Azure Database`は高いので、個人レベルで使ってる人はそんなに多くないと思いますが。
そのぶんデフォルトでレプリケーションやらバックアップやらが付いてきて高可用性を確保していたりと高性能なのですが、如何せん最低ラインが4k/月です。
スケールのこととか全く考えなくていいのは非常に楽なのですが、個人ユースでそんな限界に突き当たることなんて滅多にありませんからね。
もっと低スペックでも止まってもいいので1k/月とかのやっすーいプランもほしいところですね。