監査ログの結果から、RDSインスタンスの「本体」がAWSマネージドVPC(仮称)に建っていることに思いを馳せる

# はじめに

前回の記事で、Amazon RDS(MySQL)の監査ログについて、フォーマットを確認しました。
[Amazon RDS(MySQL)の監査ログのフォーマットを確認する【MARIADB_AUDIT_PLUGIN】](https://qiita.com/Batchi/items/3a1165f09bfbf5c59a48)


ログの読み取り方が分かったところで、実際に出力されたログを見た時にあれ？と思ったことがあるので、それについて記します。


```text:ログ出力例1
20190707 20:30:55,ip-172-23-2-48,root,10.100.xx.xx,1234567,0,DISCONNECT,,,0 
```
```text:ログ出力例2
20190808 10:15:30,ip-10-7-1-52,testdbuser,172.16.xx.xx,2345678,23456789,QUERY,testdb02,'SET autocommit=1',0
```
```text:ログ出力例3
20190909 05:25:25,ip-10-7-1-52,rdsadmin,localhost,3456789,98765432,QUERY,,'SELECT 1',0
```
##ちなみに

本記事内においては「RDSインスタンス」と表記していますが、恐らく「DBインスタンス」が正しい名称です。

# 前提の構成

例1と例2,3で、環境は異なるのですが、いずれも以下の構成となっています。

- 同一のVPCにEC2とRDSがある
- EC2とRDSは異なるサブネットに所属している
- EC2からSqlクライアントでRDSに接続している

イメージでは以下となります。

![EC2-RDS前提構成.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155963/46e304bc-fbd8-9f1b-67a3-f69d3f063c2a.jpeg)

この構成におけるRDSから出力されたログを、例として取り上げています。

# 監査ログを読んでみる

ログのフォーマットは以下の通りです。

```text:Auditログのフォーマット
[timestamp],[serverhost],[username],[host],[connectionid],[queryid],[operation],[database],[object],[retcode]
```
各フィールドの説明と、今回の構成に当てはめたときの別名を以下にまとめます。
（気を抜くと、「usernameって接続元EC2で使用しているOSユーザ名だっけ？」「hostってRDSとEC2どっちだっけ？」となる人間なので、勝手な呼称をつけています。）

| フィールド        | 説明                                                                          | エイリアス     |
|--------------|-----------------------------------------------------------------------------|-----------|
| timestamp    | 記録されたイベントの UNIX タイムスタンプ \(マイクロ秒の精度\)。                                       | タイムスタンプ   |
| serverhost   | イベントが記録されているインスタンスの名前。                                                      | 接続先RDSインスタンス   |
| username     | ユーザーの接続されたユーザー名。[^1]                                                            | 接続先DBユーザ |
| host         | ユーザーの接続元のホスト。                                                               | 接続元ホスト[^2]   |
| connectionid | 記録されたオペレーションの接続 ID 番号。                                                      | コネクションID  |
| queryid      | クエリ ID 番号。リレーショナルテーブルイベントと関連するクエリの検索に使用できます。TABLE イベントの場合、複数の行が追加されます。      | クエリID     |
| オペレーション      | 記録されたアクションの種類。指定できる値は CONNECT、QUERY、READ、WRITE、CREATE、ALTER、RENAME、DROP です。 | オペレーション   |
| データベース       | USE コマンドにより設定されたアクティブなデータベース。                                               | データベース    |
| オブジェクト       | QUERY イベントの場合、この値は実行されたクエリを表示します。TABLE イベントの場合、テーブル名を示します。                  | オブジェクト    |
| retcode      | 記録されたオペレーションのリターンコード。                                                       | リターンコード   |

[^1]: 「ユーザーの接続されたユーザー名」って「頭痛が痛い」みたいで、なかなか飲み込みづらい日本語訳ですよね…。原文は`The connected user name of the user.` なので、「接続されたユーザーのユーザー名」あたりが適当でしょうか。（まだちょっと「頭痛が痛い」感がありますが、例えば「接続されたユーザーのユーザーID」とかが同列に並ぶと思えば不自然ではないかなと。。）

[^2]: 最初はここを「接続元EC2インスタンス」と書いていたのですが、localhostが出てくることを思い出したので変えました。


冒頭で記載したログの例1-3を当てはめると以下のようになります。


| \# | フィールド        | エイリアス        | 例1                         | 例2                       | 例３                       |
|----|--------------|--------------|----------------------------|--------------------------|--------------------------|
| 1  | timestamp    | タイムスタンプ      | 20190707 20:30:55          | 20190808 10:15:30        | 20190909 05:25:25        |
| 2  | serverhost   | 接続先RDSインスタンス | ip-172-23-2-48 | ip-10-7-1-52 | ip-10-7-1-52 |
| 3  | username     | 接続先DBユーザ     | root                       | testdbuser               | rdsadmin                 |
| 4  | host         | 接続元ホスト       | 10\.100\.xx\.xx      | 172\.16\.xx\.xx    | localhost                |
| 5  | connectionid | コネクションID     | 1234567                    | 2345678                  | 3456789                  |
| 6  | queryid      | クエリID        | 0                          | 23456789                 | 98765432                 |
| 7  | オペレーション      | オペレーション      | DISCONNECT                 | QUERY                    | QUERY                    |
| 8  | データベース       | データベース       | \-                       | testdb02                 | \-                     |
| 9  | オブジェクト       | オブジェクト       | \-                       | 'SET autocommit=1'       | 'SELECT 1'               |
| 10 | retcode      | リターンコード      | 0                          | 0                        | 0                        |


以下、読んで気になったところを記します。

# 1.RDSインスタンスの「本体」があるであろうIPレンジ
なんか見慣れないIPアドレスあんだけど…。と思った話です。
ほぼこの記事で言いたいことのすべてです。


##DBをホストするサーバのIPアドレス

上記の表における\#2の「接続先RDSインスタンス」は、言い換えれば、「DBから見て、自身をホストしているサーバのホスト名」です。そして、`ip-xx-xx-xx-xx`というホスト名の命名規則は、そのサーバに`xx.xx.xx.xx`のIPアドレス（例1であれば172.23.2.48）が採番されていることを表すと考えられます。それは、EC2のデフォルトのホスト名が、そのような命名規則に則っている（ことが多い）ためです。

[Linux インスタンスのホスト名の変更]
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/set-hostname.html

>インスタンスを起動すると、プライベートの内部 IPv4 アドレスの形式のホスト名が割り当てられます。典型的な Amazon EC2 プライベート DNS 名は、ip-12-34-56-78.us-west-2.compute.internal のような形式になります。この名前は内部ドメイン、サービス (この例では、compute)、リージョン、そして**プライベート IPv4 アドレス**で構成されます。インスタンスにログインしたとき、このホスト名の一部がシェルプロンプトで表示されます (**ip-12-34-56-78** など)。

その想定が正しい前提で、以下を続けます。

##接続元EC2インスタンスが所属するIPレンジとの違い

ログの例1と例2について、IPアドレスに関する部分のみ抜きだします。

| \# | フィールド        | エイリアス        | 例1                         | 例2                       |
|----|--------------|--------------|----------------------------|--------------------------|
| 2  | serverhost   | 接続先RDSインスタンス | ip-172-23-2-48 | ip-10-7-1-52 |
| 4  | host         | 接続元ホスト       | 10\.100\.xx\.xx      | 172\.16\.xx\.xx    | 

いずれも、接続先であるRDSインスタンスと、接続元であるEC2インスタンスのIPアドレス範囲が、異なるクラスに所属しているものであることが分かります。

（クラスAやらクラスBやらについては以下を参照のこと）

[RFC 1918 - Address Allocation for Private Internets]
http://www.faqs.org/rfcs/rfc1918.html

```
3. Private Address Space

   The Internet Assigned Numbers Authority (IANA) has reserved the
   following three blocks of the IP address space for private internets:

     10.0.0.0        -   10.255.255.255  (10/8 prefix)
     172.16.0.0      -   172.31.255.255  (172.16/12 prefix)
     192.168.0.0     -   192.168.255.255 (192.168/16 prefix)

   We will refer to the first block as "24-bit block", the second as
   "20-bit block", and to the third as "16-bit" block. Note that (in
   pre-CIDR notation) the first block is nothing but a single class A
   network number, while the second block is a set of 16 contiguous
   class B network numbers, and third block is a set of 256 contiguous
   class C network numbers.
```

サンプル数が2つだけなのでなんとも言えないですが、今回の構成で言えば、必ず異なるクラスのIP範囲が割り当てられるのだろうと思います。

##他のアプローチから確認するRDSインスタンスのIPアドレス

前提構成をおさらいすると、EC2インスタンスとRDSインスタンスは同じVPCに所属しています。VPCに対してはCIDRの追加を行っていません。[^3]

[^3]: CIDRの追加をする場合でも、もともとのIPレンジと異なるクラスのプライベートIPアドレスを追加することはできません。

RDSインスタンスに接続する際にはエンドポイント（例：`mysql–instance1.123456789012.us-east-1.rds.amazonaws.com`）を指定して接続することになりますが、今回の構成においてエンドポイントを名前解決すると、EC2インスタンスと**同一のクラスのIP**が返却されます。

また、RDSインスタンスと同時に作成されるENIをマネジメントコンソールから確認しても、同様にEC2インスタンスと**同一のクラスのIPアドレス**が確認できます。

##AWSマネージドVPC（仮称）に存在している土台

- 監査ログ上でのRDSインスタンスはEC2インスタンスとは異なるクラスのIPを持つ
- 素直にRDSインスタンスに接続を試みる場合、接続先IPはEC2インスタンスと同一のクラスのIPである

上記もろもろを鑑みると、下記のような構成が妄想できます。

![EC2-RDS想定構成.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155963/694cec20-d538-477c-a476-e30be1006b12.jpeg)

- DBをホストするサーバ自体は、ユーザ（AWSカスタマー）の管理対象外のVPCに存在している
- 上記のサーバは2つ以上のネットワークインタフェースを持っており、その一つがユーザが管理するVPCに足を延ばしている
- AWSユーザから見えるRDSインスタンスのIPアドレスは、上記のネットワークインタフェースのものである

RDSにおいては、DB層より下（OS、仮想マシン、物理ホスト、物理ネットワーク…）は基本的にAWSが面倒を見てくれており、まさにその面倒を見ている場所がAWSマネージドVPC（仮称）なのかなと想像します。

面倒を見てくれる一覧。

![RDSが担ってくれるもの](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155963/333e05a1-5c06-dd42-154c-9cb53abc0f7f.png)

*20180425 AWS Black Belt Online Seminar Amazon Relational Database Service (Amazon RDS)より*
https://www.slideshare.net/AmazonWebServicesJapan/20180425-aws-black-belt-online-seminar-amazon-relational-database-service-amazon-rds-96509889/11

##ユーザの管理対象外のVPCの存在

上記の構成は名称も含めてすべて個人の妄想ですが、ユーザ管理対象外のVPCの存在は、公式の情報として確認できます。

###Amazon WorkSpaces

[Amazon WorkSpaces とは - アーキテクチャ]
https://docs.aws.amazon.com/ja_jp/workspaces/latest/adminguide/amazon-workspaces.html#architecture

上記ページより画像を引用。

![architectural_diagram-new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155963/9c40bb90-a122-cf2a-b237-d14463241454.png)


`AWS-Managed VPC`と`Customer-Managed VPC`が区別して表現されています。
WorkSpacesのインスタンスを立てた時、ユーザから見えるENIは`Customer-Managed VPC`に属するものだけです。

（このあたりを頑張って調べたときの記事はこちら。）
[[画像つき]WorkSpacesをひとまずQuick Setupで構築してアーキテクチャをざっくり理解する【アーキテクチャ編】](https://qiita.com/Batchi/items/800c96c6b76af9959aac)

###VPC内Lambda

[[発表] Lambda 関数が VPC 環境で改善されます]
https://aws.amazon.com/jp/blogs/news/announcing-improved-vpc-networking-for-aws-lambda-functions/

同じく画像を引用。

![many-enis-1024x616.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155963/08868216-ccad-37e7-2943-f5d08832f27c.png)

`AWS Lambda Service VPC`と`Customer owned VPC`が区別されています。
WorkSpacesの場合と名称は異なりますが、ユーザの管理外のVPCがあることが読み取れます。


#2.作成した覚えのないDBユーザrdsadmin
言いたいことはほぼ言い終わったので、以下はほぼおまけのようなものです。
改めてログの出力例から一部をピックアップします。


| \# | フィールド        | エイリアス        | 例1                         | 例2                       | 例３                       |
|----|--------------|--------------|----------------------------|--------------------------|--------------------------|
| 3  | username     | 接続先DBユーザ     | root                       | testdbuser               | rdsadmin                 |
| 4  | host         | 接続元ホスト       | 10\.100\.xx\.xx      | 172\.16\.xx\.xx    | localhost                |
| 8  | データベース       | データベース       | \-                       | testdb02                 | \-                     |
| 9  | オブジェクト       | オブジェクト       | \-                       | 'SET autocommit=1'       | 'SELECT 1'               |

\#3のusernameについて、例1の`root`と例2の`testdbuser`は自前で作成した覚えがあるのですが（前者はRDSインスタンス作成時のマスタユーザとして、後者はCREATE USERで）、例3の`rdsadmin`というユーザは作成した記憶がありません。

これについては、自動作成される旨、ドキュメントに記述がありました。

[Amazon RDS での MySQL のセキュリティ]
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/CHAP_MySQL.html#MySQL.Concepts.UsersAndPrivileges

>各 DB インスタンスに管理サービスを提供するために、DB インスタンスの作成時に **rdsadmin** ユーザーが作成されます。rdsadmin アカウントの権限をドロップ、名前変更、パスワード変更、または変更しようとするとエラーになります。

ざっと見た感じ、DBエンジンの種類に関わらず作成されるようです。接続元ホストは`localhost`が記録されていますが、これもRDSインスタンスの「本体」のほうを表しているのだろうなと思います。

# 3.その他

これはただ単に知らなかっただけなのですが、コネクションIDについての仕様です。

| \# | フィールド        | エイリアス        | 例1                         | 例2                       | 例３                       |
|----|--------------|--------------|----------------------------|--------------------------|--------------------------|
| 5  | connectionid | コネクションID     | 1234567                    | 2345678                  | 3456789                  |
| 6  | queryid      | クエリID        | 0                          | 23456789                 | 98765432                 |
| 7  | オペレーション      | オペレーション      | DISCONNECT                 | QUERY                    | QUERY                    |

- `CONNECT`された後に`QUERY`が実行される（そもそもの前提）
- `QUERY`がどのコネクションで実行されたかを、ログから追うことができる
- `CONNECT`の対になる`DISCONNECT`が記録される（両者はコネクションIDが同一である）

DBに疎いと、こういうことも新鮮に感じられます。

#おわりに

どこか別の場所で管理されているというのは暗黙的にわかっていたことではありましたが、監査ログという目に見える形でその存在が思い起こされたので、ちょっと得した気分になりました。

ELBなんかもきっと同じように「本体」は別のVPCで管理されているのだろうなと思います。