はじめに
Amazon RDS や Amazon Aurora に接続するときに、IAM 認証を使った接続が出来ます。通常のローカルユーザーを使った認証に加えて、IAM の権限を持ったユーザーに限定した認証が可能です。これの良いところは、パスワードを何かに管理する必要がない点です。極端な例ですが、ソースコードの中にパスワードをハードコードする必要がなくなるので、よりセキュアな環境を構成できます。
また、IAM 認証ではトークンを生成して接続するのですが、その有効期限が 15 分となっています。万が一トークンが漏れてしまっても、短い有効期限なので、セキュリティのレベルを向上できます。そもそもトークンが漏れること自体が危険なことですが、多層防御の観点を踏まえて、IAM 認証はセキュリティレベルを上げる良い方法の一つでしょう :)
この記事では、既存の Aurora 環境に IAM 認証を追加する手順を確認します。
IAM 認証を有効化
まず、RDS の画面で、IAM 認証が使われているかを確認できます。Not enabled と表示されていると使われていません。設定変更が必要です。
IAM 認証を有効化するために、Modify を押します。
Password and IAM database authentication を選択します。
Continue をおします
今回の記事は検証環境なので、即変更の Apply immediately を押します。なお、一般的には短い停止時間が発生するので、本番環境では気を付けましょう。
この記事の環境では、停止時間は確認できませんでした。接続しているセッションについても、切れることがなかったです。実は気が付かない停止時間があったかもしれません。
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 の設定は飛ばしています。ただ、実際の本番環境では、最小限な権限がベストプラクティスなので、以下の記事を参考に設定をしてみてください。
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