Aurora MySQL で IAM 認証を使った接続をしてみた

# はじめに

Amazon RDS や Amazon Aurora に接続するときに、IAM 認証を使った接続が出来ます。通常のローカルユーザーを使った認証に加えて、IAM の権限を持ったユーザーに限定した認証が可能です。これの良いところは、パスワードを何かに管理する必要がない点です。極端な例ですが、ソースコードの中にパスワードをハードコードする必要がなくなるので、よりセキュアな環境を構成できます。

また、IAM 認証ではトークンを生成して接続するのですが、その有効期限が 15 分となっています。万が一トークンが漏れてしまっても、短い有効期限なので、セキュリティのレベルを向上できます。そもそもトークンが漏れること自体が危険なことですが、多層防御の観点を踏まえて、IAM 認証はセキュリティレベルを上げる良い方法の一つでしょう :)

この記事では、既存の Aurora 環境に IAM 認証を追加する手順を確認します。



# IAM 認証を有効化

まず、RDS の画面で、IAM 認証が使われているかを確認できます。Not enabled と表示されていると使われていません。設定変更が必要です。

![image-20221103221314996.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/85a9cf8b-0d0d-564b-4710-b5d6aa12078b.png)



IAM 認証を有効化するために、Modify を押します。

![image-20221103221334420.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/f87c62b2-5c7f-4c5f-8dac-a1767b03f155.png)



Password and IAM database authentication を選択します。

![image-20221103221354665.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/fdede41a-e078-a8d5-ce9f-8307c226b6ec.png)



Continue をおします

![image-20221103221409637.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/3041c09d-77b4-1e02-4cb5-bd42c86a55b4.png)



今回の記事は検証環境なので、即変更の Apply immediately を押します。なお、一般的には短い停止時間が発生するので、本番環境では気を付けましょう。

この記事の環境では、停止時間は確認できませんでした。接続しているセッションについても、切れることがなかったです。実は気が付かない停止時間があったかもしれません。

![image-20221103221439431.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/d7fa091e-438e-9ee9-aee5-de3928beeeb3.png)



# IAM 認証用のユーザーを作成

有効化が出来たので、MySQL に接続して IAM 認証用のユーザーを作成します。

```
mysql -u admin -h <your endpoint>.ap-northeast-1.rds.amazonaws.com -p
```



MySQL に接続したあと、IAM 認証用のユーザーを作成します。名前は `iamuser01` にします。

```
CREATE USER iamuser01 IDENTIFIED WITH AWSAuthenticationPlugin as 'RDS';
```



作成したあと、確認のためユーザー一覧を表示します。`iamuser01` が表示されています。

```
mysql> select user, host from mysql.user;
+-----------------------+-----------+
| user                  | host      |
+-----------------------+-----------+
| AWS_COMPREHEND_ACCESS | %         |
| AWS_LAMBDA_ACCESS     | %         |
| AWS_LOAD_S3_ACCESS    | %         |
| AWS_SAGEMAKER_ACCESS  | %         |
| AWS_SELECT_S3_ACCESS  | %         |
| admin                 | %         |
| iamuser01             | %         |
| rds_superuser_role    | %         |
| mysql.infoschema      | localhost |
| mysql.session         | localhost |
| mysql.sys             | localhost |
| rdsadmin              | localhost |
+-----------------------+-----------+
12 rows in set (0.00 sec)
```



権限を付与します。

```
GRANT ALL ON `%`.* TO 'iamuser01'@'%';
```



付与されたことを確認します。

```
mysql> SHOW GRANTS FOR iamuser01;
+--------------------------------------------------+
| Grants for iamuser01@%                           |
+--------------------------------------------------+
| GRANT USAGE ON *.* TO `iamuser01`@`%`            |
| GRANT ALL PRIVILEGES ON `%`.* TO `iamuser01`@`%` |
+--------------------------------------------------+
2 rows in set (0.00 sec)
```



MySQL の接続から抜けます。

```
exit
```



# IAM ポリシーの作成

この記事の環境では、Administrator の権限で使っているので、IAM Policy の設定は飛ばしています。ただ、実際の本番環境では、最小限な権限がベストプラクティスなので、以下の記事を参考に設定をしてみてください。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/users-connect-rds-iam/



# IAM 認証で接続

AWS CLI で、IAM 認証用のトークンを生成します。接続先のエンドポイントなどを指定して実行します。

```
aws rds generate-db-auth-token --hostname <your endpoint>.ap-northeast-1.rds.amazonaws.com --port 3306 --username iamuser01
```



次のような文字列が表示されれば OK です。表示されたものはトークンとなっており、生成してから 15 分が利用可能です。なお、トークンをつかって接続すれば、15 分の制限は無視できます。データベースコネクションを切断して再度接続するときに、15 分が経過しているときは、再度生成するとよいでしょう。

```
<your endpoint>.ap-northeast-1.rds.amazonaws.com:3306/?Action=connect&DBUser=iamuser01&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=SECRETGW24CHU%2F20221103%2Fap-northeast-1%2Frds-db%2Faws4_request&X-Amz-Date=20221103T143320Z&X-Amz-Expires=900&X-Amz-SignedHeaders=host&X-Amz-Signature=SECRET254ae606993239c90a13995ef35d
```



トークンの文字列は長いので、変数に格納します (in Bash)

```
TOKEN="$(aws rds generate-db-auth-token --hostname <your endpoint>.ap-northeast-1.rds.amazonaws.com --port 3306 --username iamuser01)"
```



変数の中身を確認します。

```
echo $TOKEN
```



ルート証明書をダウンロードして、どこか適当な場所に保存しておきます。

```
mkdir -p ~/temp/rdsiam/
cd ~/temp/rdsiam/
wget https://s3.amazonaws.com/rds-downloads/rds-ca-2019-root.pem
```



それでは、実際に接続します！

- password にトークンを渡すことで、ログインが出来る仕組みになっています

```
mysql \
--host=<your endpoint>.ap-northeast-1.rds.amazonaws.com \
--port=3306 \
--ssl-ca=~/temp/rdsiam/rds-ca-2019-root.pem \
--enable-cleartext-plugin \
--user=iamuser01 \
--password=$TOKEN
```



接続できました。あとは、MySQL の普通の世界と同じなので、SELECT 句など自由に実行できます。

```
mysql> select * from sugi01.sample;
+----+-------+
| id | value |
+----+-------+
|  1 |    11 |
|  2 |     2 |
|  3 |     3 |
|  4 |     4 |
|  5 |     5 |
|  6 |     6 |
|  7 |     7 |
|  8 |     8 |
|  9 |     9 |
+----+-------+
9 rows in set (0.00 sec)

```



# 検証を通じてわかったこと

- IAM 認証を有効にしたとき、この記事の環境では、特にコネクションは切れなかった。再起動もなかった。
  - 以下のナレッジセンターでは、短い停止時間が発生すると記載があるので、本番環境では要注意
  - https://aws.amazon.com/jp/premiumsupport/knowledge-center/users-connect-rds-iam/
- IAM 認証を有効にしても、引き続きローカルのユーザーでアクセスが可能。IAM 認証とローカル認証を両方とも同時に利用できる。(IAM 用のユーザーを作らないといけないから、そりゃそうなんだけど)
- IAM 認証のトークンは有効期限が 15 分となる
- 一度接続したあとは、15 分を超えてもデータベースのコネクションを利用し続けられる。15 分の有効期限は、あくまでトークン自体の有効期限となる。
- 有効期限が切れたあとに、接続を試みると、次のようなエラーとなる。有効期限切れということはエラーメッセージ上はわからなさそう

```
ERROR 1045 (28000): Access denied for user 'iamuser01'@'10.0.0.163' (using password: YES)
```





# 参考URL

https://aws.amazon.com/jp/premiumsupport/knowledge-center/users-connect-rds-iam/