TL;DR
-
aws rds generate-db-auth-token
コマンドはCloudTrailに残らない - 上記で発行されるトークンで
mysql
コマンドで接続してもCloudTrailに残らない - AWS管理ポリシーの
PowerUserAccess
やAdministratorAccess
は、任意のユーザー名でAurora IAM認証ができる
はじめに
AuroraのIAM認証とは、DBユーザーにパスワードを設定せず、代わりにIAMで認証できる機能です。
MySQLの場合、通常のユーザー作成は
CREATE USER 'username'@'%' IDENTIFIED BY 'password';
ですが、IAM認証を使う場合は
CREATE USER 'username'@'%' IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS';
とします。また、別途IAM User等でAction rds-db:connect
を許可します。
そうすると、次の2つのコマンドで接続できます。
TOKEN="$(aws rds generate-db-auth-token --hostname "$HOST" --port 3306 --username "$USER")"
MYSQL_PWD="$TOKEN" mysql -h "$HOST" -u "$USER"
トークンを生成し、mysql
コマンドでパスワードの代わりにトークンを使うだけです。超便利!
問題1: 他のユーザーになりすましできちゃった...!
そこで既存のAuroraでIAM認証を使おうと思いました。
このAuroraは開発者が接続することもあるため、以前からDBユーザーを個人ごとに作成し、さらに監査ログ(Audit Log)を有効化することで、誰がどんなクエリを実行したかを記録していました。
さっそく太郎くんと花子さんのユーザーをIAM認証で作成します。
CREATE USER 'taro'@'%' IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS';
CREATE USER 'hanako'@'%' IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS';
ある日太郎くんがうっかり花子さんの名前で先ほどのコマンドを実行すると、なんと接続が成功してしまいました!
HOST='xxx'
USER='hanako' # うっかり花子にしちゃった!
TOKEN="$(aws rds generate-db-auth-token --hostname "$HOST" --port 3306 --username "$USER")"
MYSQL_PWD="$TOKEN" mysql -h "$HOST" -u "$USER"
原因は単純でした。IAM Policyで任意のユーザー名を許可してしまっていたのです。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "rds-db:connect",
"Resource": "arn:aws:rds-db:ap-northeast-1:*:dbuser:*/*",
"Effect": "Allow"
}
]
}
Resourceは
"arn:aws:rds-db:ap-northeast-1:{アカウントID}:dbuser:{DBインスタンスの識別子}/{ユーザー名}"
という形式なので、DBユーザー名をtaro
に限定したい場合は次のようになります。
"arn:aws:rds-db:ap-northeast-1:{アカウントID}:dbuser:{DBインスタンスの識別子}/taro"
IAM User名に一致させたい場合は
"arn:aws:rds-db:ap-northeast-1:{アカウントID}:dbuser:{DBインスタンスの識別子}/${aws:username}"
AssumeRoleされるRoleなら
"arn:aws:rds-db:ap-northeast-1:{アカウントID}:dbuser:{DBインスタンスの識別子}/${aws:SourceIdentity}"
などが使えます。
これで太郎くんと花子さんは自分への「なりすまし」に怯えなくて済むようになりました。めでたしめでたし... とはならなかったのです。
問題2: PowerUserAccessで許可されちゃってる〜
このアカウントでは複数の管理者が、AWS管理ポリシーのPowerUserAccessやAdministratorAccessを持っていました。
試しにPowerUserAccess
を持つ管理者がtaro
で接続を試みると、なんと成功してしまいました!
HOST='xxx'
USER='taro'
TOKEN="$(aws rds generate-db-auth-token --hostname "$HOST" --port 3306 --username "$USER")"
MYSQL_PWD="$TOKEN" mysql -h "$HOST" -u "$USER"
いえ、そんなに驚くことではないかもしれません。先ほどと同様、PowerUserAccess
でrds-db:connect
が任意のユーザー名で許可されているだけです。それを拒否すれば良いので、例えばIAMやSCPにEffect: Deny
でいい感じのルールを入れましょう。
ただ、会社やサービスによっては、諸般の事情でこれがちょっと面倒くさい場合もあります...(SSOを使っている等。できるけど少し大変、というニュアンス)
問題3: CloudTrailに記録されない!?
そこで管理者は妥協を考えました。「なにかあったときに監査ログでなりすましを確認すればいいや!」
前述の通りAuroraの監査ログ(Audit Log)は有効化しています。さらにAWSではCloudTrailで、全てのAPI Callを記録できます。
CloudTrailが設定してあることを確認して、管理者はふたたびtaro
で接続しました。
HOST='xxx'
USER='taro'
TOKEN="$(aws rds generate-db-auth-token --hostname "$HOST" --port 3306 --username "$USER")"
MYSQL_PWD="$TOKEN" mysql -h "$HOST" -u "$USER"
ところが、CloudTrailにログが出てきません。全てのAPI Callが記録されるはずなのに...
そこで試しにPCのインターネット接続を切って3行目のコマンドを実行したところ、なんと成功してしまいました。
aws rds generate-db-auth-token --hostname "$HOST" --port 3306 --username "$USER"
そうです。このコマンドはトークンを生成するだけで、API Callは行っていませんでした。IAM認証は4行目のmysqlへの接続時に行われていたのです。
では、その4行目でCloudTrailにログはでないのでしょうか?
MYSQL_PWD="$TOKEN" mysql -h "$HOST" -u "$USER"
残念ながらログは出ませんでした。これは完全な推測ですが、Auroraの内部でIAM認証が行われているからだと思います。
というわけで、CloudTrailでなりすましを確認することはできないので、管理者は頑張ってIAMで制御することにしましたとさ。
おわりに
以上のストーリーはフィクションですが、AuroraのIAM認証で接続してもCloudTrailに何も残らないことはサポートに確認しました。その際、「他のお客様からもご要望いただいており、本ケースについても担当部署にフィードバックするが、実装有無および時期はお約束できない」旨もご返信いただきました。今後に期待ですね。
ということで、現時点でAuroraのIAM認証を使う際は十分お気をつけください。
駄文をお読みいただきありがとうございました。