LoginSignup
5
2

More than 1 year has passed since last update.

Aurora MySQLでIAM認証する手順と検証メモ

Last updated at Posted at 2021-07-19

Aurora MySQLでIAM認証を検証したので、備忘録を兼ねて諸々メモ。

AuroraのIAM認証とは?

DBユーザーに、個別のパスワード入力の代わりにIAMクレデンシャルで認証する機能。
DBごと、ユーザーごとのパスワード管理が不要になる。
スロットルのリスクがあるためアプリケーションの認証には不向きだが、運用に伴う人による認証については一考の価値がある。

Aurora側での設定

  • クラスターでIAM認証を有効化しておく。マネジメントコンソールでいうと、インスタンス設定(≠クラスター設定)の以下が該当設定。
    スクリーンショット 2021-07-20 午前0.51.48.png
  • データベースで、IAM認証を有効にしたDBユーザーを作成する。IAM認証は、あくまでこのDBユーザーに対して、AWSプロファイルのIAMクレデンシャルでログインする行為であって、DBユーザーがないと機能しない点に注意。
DBユーザーの作成
CREATE USER ssotest IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS';

踏み台インスタンスでの設定

  • DB接続用のmysqlクライアントを事前にインストールしておく。
    • 実は微妙にハマリポイント。Amazon Linux 2で普通にsudo yum install mysqlとすると、MariaDB互換クライアントがインストールされる(Amazon Linux 1だとMySQL純正クライアントが入る)のだが、MariaDB互換クライアントを使う場合、公式ドキュメントに記載のオプションではログインできない(後述の通り、別のオプションを使えば行けるが、そこに辿り着くまで大分かかった)。
    • MySQL純正クライアントをインストールしてもよいが、アークテクチャーを選んでローカルインストールなど若干面倒くさい手順が必要になるので、ここでは一行で済むMariaDB互換をインストールする。
  • IAM認証時は、TLS接続設定に関わらずAuroraのCA証明書が必要になるので、ホームディレクトリあたりにwgetしておく。
    • 以前はrds-ca-2019-root.pemだったが、リージョンごとの差異を吸収するglobal-bundle.pemに変わったらしい。

(2023/4/21追記) 以前は5年ごとにCA証明書の更新が必要だったが、2023年のアップデートで、長期間利用可能な認証局がサポートされた。現時点では、Aurora/MySQLでは従来の5年もの(rds-ca-2019)の他、40年もの(rds-ca-rsa2048-g1)が利用可能。詳細はこちらを参照。

CA証明書の保存
% wget https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem

権限付与の方針決定

  • DBへのアクセスは一般に、パブリックアクセスは勿論、任意の端末からの接続を禁止するために、VPC内の特定のEC2インスタンス(踏み台)からのアクセスにセキュリティグループで縛ることが多いと思う。そうでないパターンも当然あり得るが、ここでは一応、踏み台パターンを前提とする。
  • IAM認証には接続トークンの生成が必要になるが、踏み台からのIAM認証パターンは以下の二種類が考えられる。違いは、**「誰の権限で・どこでトークンを生成するか」**の観点。
    • 踏み台のインスタンスプロファイル(ロール)にIAM認証を許可するポリシーを付与。接続トークンは踏み台内で生成して環境変数に格納。
    • 踏み台には権限を付与せず、それ以外のIAMロールにIAM認証を許可するポリシーを付与。接続トークンは別端末で生成してコピペ。
  • 具体的には、以下のようなポリシーをどこのロールに割り当てるかの話になる。
IAM認証ポリシー例
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "rds-db:connect"
            ],
            "Resource": [
                "arn:aws:rds-db:ap-northeast-1:123456789012:dbuser:test-cluster/ssotest"
            ],
            "Condition": {
                "ForAnyValue:StringLike": {
                    "aws:PrincipalOrgPaths": "o-oXXXXXXXXX/r-YYYY/ou-ZZZZZZZZZZZZZ/*"
                }
            }
        }
    ]
}
  • プロコンはざっくり以下のようなイメージ。今回は踏み台の多系統化を避けて「別のIAMロール案」とする。具体的にはAWS SSOを使い、アクセス権限セットにrds-db:connectを付与する。
インスタンスプロファイル案 別のIAMロールに付与する案
利点 認証操作がシンプル 踏み台は一系統でよい
欠点 権限ごとに踏み台を分岐する必要がある トークンを持ち込む必要がありひと手間かかる

接続

  • まずは認証トークン取得。前述の方針に従い、今回はAWS SSOでログイン後、踏み台の外でトークンを取得する(踏み台でトークン生成コマンドを叩くと、踏み台のインスタンスプロファイルの権限内で生成され、今回だとどこにも接続できないことになるため)。
認証トークン取得
% aws sso login --profile ssotest-profile
% aws rds generate-db-auth-token \
> --hostname hoge \
> --region ap-northeast-1 \
> --port 3306 \
> --username ssotest \
> --profile ssotest-profile
  • トークンが生成されたら、クリップボードにコピーする。本来は環境変数に格納するのが楽なのだが、今回は踏み台に持ち込む必要上、コピペで対応する。
  • 踏み台にSSM Sessions Manager等でログイン後、DB接続を実行する。ここではMariaDB互換クライアントのパターンを使用するが、参考までにMySQL純正クライアントのパターンも併記しておく。
DB接続(MariaDB互換クライアントのパターン)
% TOKEN='(先程取得したトークンの文字列をそのままコピペ)'
% mysql -h <Auroraエンドポイント>.ap-northeast-1.rds.amazonaws.com \
> --port=3306 \
> --user=ssotest \
> --password=$TOKEN \
> --ssl-ca=~/global-bundle.pem \
> --enable-cleartext-plugin

(2023/4/21追記) Amazon Linux 2023がリリースされたこともあり、久しぶりに試したところ、MariaDB互換クライアントでのオプションが --default-auth=mysql_clear_password から --enable-cleartext-plugin (MySQL互換クライアントと同じ)に変わっていた。

DB接続(MySQL互換クライアントのパターン)
% mysql -h <Auroraエンドポイント>.ap-northeast-1.rds.amazonaws.com \
> --port=3306 \
> --user=ssotest \
> --password=$TOKEN \
> --ssl-ca=~/global-bundle.pem \
> --enable-cleartext-plugin

無事繋がったら完了。
なかなかMySQLのプロンプトが出ないな?という場合は、セキュリティグループを見直してみることをお薦めする。ちゃんと3306が許可されてるかとか、Aurora側でEC2側セキュリティグループをIngressに含めているか、など。
Access Deniedの際は以下のようなエラーが即時返ってくるので、そうでない場合はまずネットワークを疑う。

AccessDeniedな場合の接続エラー
ERROR 1045 (28000): Access denied for user 'ssotest'@'XXX.XXX.XXX.XXX' (using password: YES)

小ネタ

  • トークンは15分だけ有効。
    • 一度生成したらいつでもどこでも再利用できるわけではなく、一定期間で切れるようになっている。
  • 別アカウントで取得したトークンは使えない。
    • IAMポリシーがどうあれ、アカウントをまたいでトークンを再利用することはできない。例えば、開発アカウントでたまたまrds-db:connect権限を持っていてトークンを生成できたとしても、それを使って本番アカウントのDBにログインすることができないようになっている。
  • 「インスタンスプロファイル案」を選択して踏み台からトークンを生成する場合、当たり前だが、RDSのAPIエンドポイントへの経路が必要になる。
    • 踏み台のEgressをガチガチに縛っている場合は、VPCエンドポイントが必要になるかも。
  • AdministratorAccessなど、iam:*を保持している権限だと、ポリシー内容に拘わらず全部接続できてしまう。
    • 検証する際は注意しておかないと、想定した挙動にならなくて時間を無駄にする。
  • AWS SSOでも使える。
    • 今は改修されているが、以前は公式ドキュメントに「DBユーザー名はロール名と同じにせよ」という誤記があり、ロール名にアカウントごとのランダム文字列が付記されるAWS SSOでは運用上成立しないように見えていたが、原文は"Make sure the specified database user name is the same as a resource in the IAM policy for IAM database access."なので単なる誤訳だったらしい。
  • Resourceの部分はワイルドカードを使える。つまり、
Resource句(個別指定)
            "Resource": [
                "arn:aws:rds-db:ap-northeast-1:123456789012:dbuser:test-cluster/ssotest"
            ],

は、要件に応じて、以下のようにも書き変えることができる。

Resource句(ワイルドカード)
            "Resource": [
                "arn:aws:rds-db:*:*:dbuser:*/ssotest"
            ],

ただし、このままだといささか範囲が広すぎるので、せめてOrganizationsで縛るくらいはしておくこと。要件によっては、対象アカウントを本番とそれ以外に分けたり、対象クラスターを分けたりとかもあるかも知れない。

Condition句(OU縛り)
            "Condition": {
                "ForAnyValue:StringLike": {
                    "aws:PrincipalOrgPaths": "o-oXXXXXXXXX/r-YYYY/ou-ZZZZZZZZZZZZZ/*"
                }
            }

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2