こんにちは。SRE1課の冨塚です。
RDSへログインする時に利用するユーザパスワードは定期的にローテーションしなければならない!という要件に出くわした時にオロオロせず、そしたらAWS Secrets Managerを使いましょう。というために検証しました。
作業概要
- Secrets Managerに登録されているRDSログインパスワード情報をLambdaを使って自動ローテーションする
- 下記公式ドキュメントのチュートリアルを参考にすすめていく
作成リソース
- Amazon RDS-AuroraMySQL
- Amazon EC2-接続確認用
- AWS Secrets Manager
- AWS Lambda
構成図
Step0: 接続確認用EC2の作成
RDSログインパスワード更新前と更新後に接続できることを確認するためにRDS接続確認用にEC2を作成します。SSMから操作したかったのでSSMの権限を持つIAMロールをアタッチしました。
EC2作成は下記ドキュメントを参考に進められます。
チュートリアル: Amazon EC2 Linuxインスタンスの開始方法
- RDSへの接続確認するためにmysqlコマンドが入っていることを確認
[ssm-user@aws-test bin]$ which mysql /usr/bin/mysql
Step1: 検証用RDSの作成
RDSはStep0で作成したEC2と同じVPCに作成しました。プライベードサブネットへ作成し外部からの接続は許可しない構成としました。下記ドキュメントを参考に作成は進められます。
パスワードが変わったことを確認するためにRDS作成時は簡単なものを利用しました。実際に作成される場合はあるていど強固なものを設定してください。
- EC2からの接続ログ
[ssm-user@aws-test bin]$ mysql -h test-rds-secrets-rotation-instance-1.cylfrukx3obg.ap-northeast-1.rds.amazonaws.com -u admin -p123456789 Welcome to the MariaDB monitor. Commands end with ; or \g. Your MySQL connection id is 21 Server version: 5.7.12 MySQL Community Server (GPL) Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MySQL [(none)]> MySQL [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.01 sec)
Step2: シークレットの作成
Secrets Manager でシークレットを作成します。作成ウィザードに従い必要な情報を入力していきます。この段階では自動ローテーションは無効で作成します。
「新しいシークレットを保存する」をクリックし、シークレットの種類を選択画面で「RDSデータベースの認証う情報」を選択します。Step1で作成したRDSへのログイン情報と対象RDSを選択し次へ。
シークレットの名前を入力し次へ。
シークレット作成時は自動ローテーションを無効にするを選択し次へ。
作成内容に問題なければ保存をクリック。
シークレット作成後に設定された値を確認します。対象シークレットを選択し、「シークレットの値を取得する」をクリックすると設定されている値が確認できます。
Step3: シークレットをローテーションさせる
ここから実際シークレット情報のローテーションを行うための設定になります。
- 作成したシークレットを選択し、「ローテーションを編集」をクリックします。
- 「ローテーションを実行するための新しいLambda関数を作成します」を選択しLmabdaの関数名を指定します。このシークレットを使うが選択されていることを確認し保存します。保存を選択すると裏でCloudFormationがLambda関数を作成してくれます。
- CloudFormationによるLambdaの作成が完了すると下記画面のように有効化表示になります。
作成されたLambdaを確認すると実行されている形跡がありました。ローテーション有効化のタイミングで初回のシークレット変更が行われるようです。
トラブルシューティング
ローテーションの有効化のタイミングでLambdaが実行されたのですが、シークレット情報は更新されていませんでした。実行ログを確認するとタイムアウトしているようです。
- Lambda実行ログ
START RequestId: d4388c66-xxxx-xxxx-xxxx-49662b7d4c51 Version: $LATEST [INFO] 2020-12-25T12:44:03.271Z d4388c66-xxxx-xxxx-xxxx-49662b7d4c51 Found credentials in environment variables. END RequestId: d4388c66-xxxx-xxxx-xxxx-49662b7d4c51 REPORT RequestId: d4388c66-xxxx-xxxx-xxxx-49662b7d4c51 Duration: 30030.55 ms Billed Duration: 30000 ms Memory Size: 128 MB Max Memory Used: 31 MB 2020-12-25T12:44:33.072Z d4388c66-xxxx-xxxx-xxxx-49662b7d4c51 Task timed out after 30.03 seconds
なぜだ...なんだ...なにが悪い... いろいろと確認しながら唸っていたのですが、チュートリアルを改めて確認すると下記の記述がありました。
重要 ローテーションを有効にするには、ネットワーク環境で Lambda ローテーション関数がお客様のデータベースと Secrets Manager サービスと通信できるように許可する必要があります。このチュートリアルでは、パブリックインターネットアクセスを使用してデータベースを設定し、Lambda がパブリック IP アドレスを使用してデータベースにアクセスするローテーション関数を自動的に設定します。データベースインスタンスへのパブリックインターネットアクセスをブロックする場合、Lambda 関数をデータベースインスタンスと同じ VPC 内で実行できるように設定する必要があります。次に、プライベート Secrets Manager エンドポイントで VPC を設定するか、NAT ゲートウェイを使用してパブリックインターネットアクセスを持つ VPC を設定して、Lambda ローテーション関数がパブリック Secrets Manager エンドポイントにアクセスできるようにする必要があります。
ローテーション用LambdaがSecrets ManagerのエンドポイントにアクセスするためにパブリックアクセスかSecrets Managerのエンドポイントの設定が必要とのこと。改めてLambdaの設定内容を確認してみると構築したRDSと下記項目を引き継ぎ同じ設定になるようです。
- 作成先VPC
- 作成サブネット
- アタッチするSG
RDSにアタッチしているSGはアウトバウンドのルールは何も指定せずローカルネットワークからのインバウンドのみを許可していました。それが原因でSecrets Managerのエンドポイントにアクセスができなかったようです。LambdaにアタッチするSGを下記のものへ変更しました。
方向 | ポート範囲 | ソース |
---|---|---|
インバウンド | - | - |
アウトバウンド | 443 | 0.0.0.0/0 |
3306 | 0.0.0.0/0 |
- LambdaのSGを変更後に「すぐにシークレットをローテーションさせる」をクリックしてみます。
- 確認画面がでるので問題なければ「ローテーションさせる」をクリック
前回のローテーションが失敗している場合はエラー表示がありますが、Lambdaは再実行されました。
- Lambda実行ログ
START RequestId: b32eb3a6-xxxx-xxxx-xxxx-e54ba0ec5847 Version: $LATEST [INFO] 2020-12-25T12:54:57.442Z b32eb3a6-xxxx-xxxx-xxxx-e54ba0ec5847 createSecret: Successfully retrieved secret for arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxx:secret:rds-rotation-secret-PfAPbb. END RequestId: b32eb3a6-xxxx-xxxx-xxxx-e54ba0ec5847 REPORT RequestId: b32eb3a6-xxxx-xxxx-xxxx-e54ba0ec5847 Duration: 294.28 ms Billed Duration: 295 ms Memory Size: 128 MB Max Memory Used: 78 MB START RequestId: fabfcc02-xxxx-xxxx-xxxx-a4ddf21cd690 Version: $LATEST [INFO] 2020-12-25T12:54:57.802Z fabfcc02-xxxx-xxxx-xxxx-a4ddf21cd690 setSecret: AWSPENDING secret is already set as password in MySQL DB for secret arn arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxx:secret:rds-rotation-secret-PfAPbb. END RequestId: fabfcc02-xxxx-xxxx-xxxx-a4ddf21cd690 REPORT RequestId: fabfcc02-xxxx-xxxx-xxxx-a4ddf21cd690 Duration: 318.93 ms Billed Duration: 319 ms Memory Size: 128 MB Max Memory Used: 78 MB START RequestId: 731b78c4-xxxx-xxxx-xxxx-84519d3a68f0 Version: $LATEST [INFO] 2020-12-25T12:54:58.158Z 731b78c4-xxxx-xxxx-xxxx-84519d3a68f0 testSecret: Successfully signed into MySQL DB with AWSPENDING secret in arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxx:secret:rds-rotation-secret-PfAPbb. END RequestId: 731b78c4-xxxx-xxxx-xxxx-84519d3a68f0 REPORT RequestId: 731b78c4-xxxx-xxxx-xxxx-84519d3a68f0 Duration: 311.22 ms Billed Duration: 312 ms Memory Size: 128 MB Max Memory Used: 78 MB START RequestId: 79655a40-xxxx-xxxx-xxxx-71595461f1de Version: $LATEST [INFO] 2020-12-25T12:54:58.497Z 79655a40-xxxx-xxxx-xxxx-71595461f1de finishSecret: Successfully set AWSCURRENT stage to version e0503e52-e7d1-4457-8bc8-a55c5c7d8097 for secret arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxx:secret:rds-rotation-secret-PfAPbb. END RequestId: 79655a40-xxxx-xxxx-xxxx-71595461f1de REPORT RequestId: 79655a40-xxxx-xxxx-xxxx-71595461f1de Duration: 318.37 ms Billed Duration: 319 ms Memory Size: 128 MB Max Memory Used: 78 MB
- 更新されたシークレット情報
更新されたパスワードを利用してEC2から接続することもできました。
- ログイン確認
[ssm-user@aws-tomi-test bin]$ mysql -h test-rds-secrets-rotation-instance-1.cylfrukx3obg.ap-northeast-1.rds.amazonaws.com -u admin -p123456789 ERROR 1045 (28000): Access denied for user 'admin'@'192.168.0.62' (using password: YES) [ssm-user@aws-tomi-test bin]$ [ssm-user@aws-tomi-test bin]$ mysql -h test-rds-secrets-rotation-instance-1.cylfrukx3obg.ap-northeast-1.rds.amazonaws.com -u admin -p'IkYxxxxxxxxxx[K}h*hV,S[e>' Welcome to the MariaDB monitor. Commands end with ; or \g. Your MySQL connection id is 26 Server version: 5.7.12 MySQL Community Server (GPL) Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. MySQL [(none)]> MySQL [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | +--------------------+ 4 rows in set (0.00 sec) MySQL [(none)]>
まとめ
チュートリアル通りに進めるだけで割と簡単にシークレット情報のローテーションができました。今回はパスワード情報の更新する方法ですが、Lambdaを編集し特定シークレットを更新する方法も可能と思います。またプログラム内でシークレットを参照するようになっていればローテーション後もプログラム側を変更する必要もなく利用可能と思います。
検証してみて下記点は注意が必要な点だと感じました。
- ローテーション有効化時にLambdaは動作する
- LambdaからSecrets Managerのエンドポイントが参照できること
それではよいAWSライフをお送りください。
swx-tomitsuka (執筆記事の一覧)