Cloud SQLへのprivate ip 接続でハマった話

## 概要
Cloud SQL(MySQL)に対してprivate ipを使ってアクセスしたときに、何をチェックしたかをメモする
ハマったからにはきちんとログを残す

## 現象
GCE から Cloud SQLに対してprivate ipでアクセスができない

```
$ mysql -u root -p --host [private ip]
ERROR 1045 (28000): Access denied for user 'root'@'[GCEのprivate ip]' (using password: YES)
```
(Access deniedと言われている時点でVPCの構成は問題ないのだが、本稿は調べたこと自体を書くので一旦無視する)

## 観点
1. VPCの接続構成が正しいか
2. アクセスログがあるかどうか
3. Cloud Proxyで接続できるのか（MySQLのusername/passwordが合っているか、private ipでいけるのかなど
4. MySQLのUserテーブルのHostで許可設定がされているか
5. SSL/TSLの設定が間違っていないのか

### 1. VPCの接続構成が正しいか
GCPのdefaultのvpcネットワークに接続しているものとして仮定する。
対象のインスタンスの設定画面からネットワークインタフェースを参照し、「ネットワーク インターフェースの詳細」に移動する
赤丸のボタンを押しネットワークの接続テストを作成する（最初はAPIを許可するというボタンになっているのでonにしてテストを実施できるようにする）

<img width="1307" alt="スクリーンショット 2020-08-08 0.27.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75299/a60d3785-b781-60eb-336f-eebffbf1c8aa.png">

接続テストにて、今回のアクセスについて記載する。

<img width="505" alt="スクリーンショット 2020-08-08 0.27.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75299/365344ce-734d-5f80-688b-7237c23e4c60.png">

到達可能になっている場合は、「理論的」に接続が可能である（パケットは転送されている可能性がありますってのは、理論的には送ってないけど、構成としては届きますっていうこと）

<img width="509" alt="スクリーンショット 2020-08-08 0.35.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75299/6c00f7c7-afcf-7d22-2831-7f208219f266.png">

もしここで到達可能にならない場合は、VPCネットワークピアリングのlist( https://console.cloud.google.com/networking/peering/list
 )から対象を参照し、
対象のピアリングが、GCEの使っているネットワークインタフェースのVPCネットワークと同じであることを確認する。（今回defaultを想定するので対象のピアリングがdefaultのVPCネットワークに所属していることを確認する）

同じVPCネットワークではあるが、到達可能にならない場合、サブネット ピアリング ルートにCloud SQLのprivate ipが所属していない可能性がある（Cloud SQLでprivate ip作成をした場合はここは問題ないはずだが。。。 [こちらの方の現象と同じ](https://tech.zeals.co.jp/entry/2020/03/05/140627?utm_source=feed)になっている可能性もあるので注意する)

全部チェックできたら2に進む

##### 1.の補足
ネットワーク詳しくない場合、この接続テスト機能で確認していくのが良いと思われる。
https://cloud.google.com/network-intelligence-center/docs/connectivity-tests/how-to/running-connectivity-tests?hl=ja

### 2. アクセスログがあるかどうか
構成が正しいことが確認できたら、対象のCloud SQLインスタンスに対してそもそもアクセスが本当に届いているのかをログで見てみる
対象の時間辺りに以下のクエリで検索してログが出ていることを出ていることを確認する

```
resource.type="cloudsql_database"
severity=INFO
textPayload:"Access denied for user"
```

ない場合は1. で、VPCの設定がきちんとできているかをもう一度確認する。またはインスタンスが動いているかを確認する。
ある場合は3に進む

##### 2.の補足

Cloud Loggingのクエリの書き方は覚えたほうがいい
https://cloud.google.com/logging/docs/view/advanced-queries?hl=ja

### 3. Cloud Proxyで接続できるのか（MySQLのusername/passwordが合っているか、private ipでいけるのかなど

Cloud Proxyを使って接続してみる
インストールはドキュメントの通り対応するとしてprivate ipを使ってアクセスする
https://cloud.google.com/sql/docs/mysql/sql-proxy?hl=ja

```
$ ./cloud_sql_proxy -ip_address_types=PRIVATE -instances=[対象のcloud sqlのinstance id]
$ mysql -u root -p -S /cloudsql/[対象のcloud sqlのinstance id]
```

接続できたなら、username/passwordは合っている。private ipも動いている。4へ進む。
できない場合username/passwordが間違っている可能性が高い。Cloud SQLのコンソール画面からrootのパスワードを変更してみる。
それでもできない場合、public ipが空いているのであれば(許可ipはなくても良い)、-ip_address_typesのflagを消してpublic ipでのアクセスを試してみる。それでもできない場合はインスタンスが停止している、または、4のユーザのHOSTの設定が限りなく狭いと思われる。(rootなのであんま考えにくいけど。。。)
CloudSQLのコンソール画面から許可ホストを%となるようにユーザを作成してアクセスできるか確認する
それでも、できなかったら、GCEのインスタンスについているサービスアカウントのiamの設定、またはインスタンスのアクセスscopeにて、cloud sqlへの接続許可がついていないと思われる。（この場合アクセスログには残らない気がするが。。。）

#### 3.の補足
cloud sql proxyでprivate ipだけでの接続やtcpでの接続ができるので、色々チェックできるのがすごい
TCPの場合

```
$ ./cloud_sql_proxy -ip_address_types=PRIVATE -instances=[対象のcloud sqlのinstance id]=tcp:3306
$ mysql -u root -p --host 127.0.0.1 --port 3306
```

### 4. MySQLのUserテーブルのHostで許可設定がされているか
Cloud SQLのコンソール画面からユーザ一覧をみて、許可されているホストを確認する
(rootなのに)制限されているのであれば、制限内のipからprivate ipでアクセスしてみる。
ホストの値が `%` になっている、または制限内のipなのにアクセスできない場合、5に進む

#### 4.の補足
Cloud SQLのコンソール上で見れるのは `mysql` データベースの `user` テーブルである。
ユーザのgrantについてはMySQLにloginしないと見れない（今回はloginできるかの問題なので、grantはあまり関係ない

### 5. SSL/TSLの設定が間違っていないのか
- SSL/TSLの設定をしている場合、その期限が切れているか
- またその証明書が正しいかどうか
- MySQLへのアクセス時に証明書を使っているか
- SSL/TSLの設定をOFFにしてprivate ipでアクセスできるか(public ip直でアクセスしている場合は、OFFにしてはいけない)

以上をチェックする。
Cloud Proxyを使ってのアクセスの場合、SSL/TSLの証明書などがなくてもいけるので、いつもCloud Proxyを使ってたから特に気にしてない人はここでハマるかも知れない（まぁ、ハマりましたけど
ここまでくればほぼ接続できるはず。。。

#### 5.の補足
SSL/TSLをONにして、SSL/TSLの証明書がないって場合、パスワード間違いと同じエラーがでてくる
設定はきちんと見直そう

## まとめ
よくわからないで設定を変更するのはやめておこう。。。(今回のSSL/TSLの設定もいつしたのか覚えてない