Amazon RDS と AWS Secrets Manager の統合を試して理解する。

記事タイトルとURLをコピーする

こんにちは😺技術課の山本です。

2022 年 12 月 22 日に 以下のアップデートがありました。

aws.amazon.com

RDS のマスターユーザー情報(ユーザー名とパスワード)を、Secrets Manager で管理する際に、RDS 側からの操作で完結できるようになりました。
本機能について検証するきっかけがありましたので、どういった仕様になるのか、本記事に書き残すことにしました

アップデート以前

アップデート以前は、以下の流れで、RDS と Secret Manager を連携させていました。

  1. RDS にクラスターやインスタンスを作成 (既存では不要)
  2. Secrets Manager にシークレットを作成
  3. シークレットをローテーションする Lambda 関数を RDS / Secrets Manager と疎通できるように設定

参考ブログ: AWS Secrets Managerに保存されたRDSのログインパスワードをローテーションしてみた件 - サーバーワークスエンジニアブログ

アップデート後

アップデート後は、以下を実施するのみになりました。

  1. RDS にクラスターやインスタンスを作成する際に、「AWS Secrets Manager でマスター認証情報を管理する」を選択する。
    または、存在するインスタンスを「変更」し、「RDSのマスター認証情報をAWS Secrets Manager で管理する」を選択する。

RDS にクラスターやインスタンスを作成する際に、「AWS Secrets Manager でマスター認証情報を管理する」を選択する。

作成時に「RDSのマスター認証情報をAWS Secrets Manager で管理する」のチェックボックスが出ます。(デフォルトではチェックなしでした。)

チェックを入れると、下にある「パスワードの自動生成」や「マスターパスワード」の入力項目が消えました。
代わりに、Secret Manager でパスワードを管理する際に使用する KMS キーの選択項目が表示されました。

存在するインスタンスを「変更」し、「RDSのマスター認証情報をAWS Secrets Manager で管理する」を選択する。

RDS の場合も、Aurora クラスターの場合にも、インスタンスを選択し「変更」 を押して変更できます。

参考:Amazon RDS DB インスタンスのマスターユーザーのパスワードをリセットする | AWS re:Post

インスタンスの変更時に「RDSのマスター認証情報をAWS Secrets Manager で管理する」のチェックボックスが出ます。

チェックを入れると、下にある「パスワードの自動生成」や「マスターパスワード」の入力項目が消えました。

なお、「メンテナンスウインドウ」とは連携できません。
「すぐに適用」する必要があります。

変更中の画面です。

利用可能になりました。

Secrets Manager で管理しているパスワードで RDS に接続するために、アプリケーションコードで必要な改修

統合を実施すると Secrets Manager にシークレットができます。詳細は見出し「Secrets Manager にできるもの」を参照ください。
Secret Manager のサービス画面から シークレットを参照すると、サンプルコードを入手できます。
以下は Python の例です。

# Use this code snippet in your app.
# If you need more information about configurations
# or implementing the sample code, visit the AWS docs:
# https://aws.amazon.com/developer/language/python/

import boto3
from botocore.exceptions import ClientError


def get_secret():

    secret_name = "rds!cluster-XXXXXXXX"
    region_name = "ap-northeast-1"

    # Create a Secrets Manager client
    session = boto3.session.Session()
    client = session.client(
        service_name='secretsmanager',
        region_name=region_name
    )

    try:
        get_secret_value_response = client.get_secret_value(
            SecretId=secret_name
        )
    except ClientError as e:
        # For a list of exceptions thrown, see
        # https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
        raise e

    # Decrypts secret using the associated KMS key.
    secret = get_secret_value_response['SecretString']

    # Your code goes here.

シークレットの強制ローテーションを試す

RDS の場合も、Aurora クラスターの場合にも、インスタンスを選択し「変更」 を押します。
「シークレットをすぐに更新する」のチェックボックスにチェックします。

「すぐに適用」にチェックし変更します。

変更が走ります。

利用可能になりました。

既存のセッションには影響なく、新しく作成するセッションから新しいパスワードが有効になります。
念のため、新しく作成するセッションに、1つ前のパスワードを入れるとエラーになりました。

新しいパスワードを入れると接続できました。

なお、「メンテナンスウインドウ」とは連携できません。 メンテナンスウインドウで適用しようとするとエラーになります。

AWS CLI のドキュメントにも、メンテナンスウインドウではなく、「すぐに適用 (change immediately)」を選択するよう記述があります。

Constraints: You must apply the change immediately when rotating the master user password.

AWS CLI を使用して、Amazon RDS と AWS Secrets Manager の統合を試す

※ Aurora クラスターの例です。RDS の場合は modify-db-instance に置き換えください。

存在するインスタンスを「変更」し、「RDSのマスター認証情報をAWS Secrets Manager で管理する」を選択する。

aws rds modify-db-cluster --apply-immediately --manage-master-user-password --db-cluster-identifier <クラスター名>

存在するインスタンスを「変更」し、「RDSのマスター認証情報をAWS Secrets Manager で管理する」を選択するのをやめる。新しいマスターユーザーのパスワードを自身で管理する。

aws rds modify-db-cluster --apply-immediately --no-manage-master-user-password --db-cluster-identifier <クラスター名> --master-user-password    <マスターユーザーのパスワード>

シークレットの強制ローテーション

aws rds modify-db-cluster --apply-immediately --rotate-master-user-password --db-cluster-identifier <クラスター名>

AWS CloudFormation を使用して、Amazon RDS と AWS Secrets Manager の統合を試す

CloudFormation での作成もサポートしています。(強制ローテーションはなし)
詳細は割愛します。以下のドキュメントを参照ください。

Aurora クラスター

AWS::RDS::DBCluster - ManageMasterUserPassword

RDS

AWS::RDS::DBInstance - ManageMasterUserPassword

Secrets Manager にできるもの

RDS のサービス画面で対象の クラスタ を選択して、シークレットの ARN (Amazon Resource Name) を確認可能です。

Secrets Manager のサービス画面をみると、自動的にシークレットを作成していました。
シークレットには、 rds! という接頭辞がつきました。

このシークレットは Amazon RDS (rds) によって作成されました。 このシークレットは Amazon RDS (rds) によって管理されるため、シークレット値を変更することはできません。ただし、シークレットは他の方法で変更できる場合があります。

上記文言を試すために、シークレットの値を書き換えてみました。

結果、エラーになり失敗しました。

エラー文:

This secret is managed by Amazon RDS (service ID: rds), and you must use that service to update it. For more information, see https://docs.aws.amazon.com/secretsmanager/latest/userguide/service-linked-secrets.html. 和訳:このシークレットは Amazon RDS (サービス ID: rds) で管理しています。更新するにはRDS サービスを使用し行う必要があります。詳細については、リンクを参照ください。

なお、シークレットはデフォルトで 7 日の自動ローテーションとなっていました。

自動ローテーションの設定は、Secret Manager から変更できました。

実際にローテーションされていました。

また、「すぐにシークレットをローテーションさせる」ボタンでもローテーションは可能でした。

念のため、Secrets Manager から書き換えたパスワードで ODBC 接続を試したところ、接続もできていました。
(あんまり画面を貼る意味はないものの、テンション上がったので・・。また、Lambda の実行ログが見えないので、証明するログもなく・・。)

Lambda 関数

シークレットのローテーションを行う Lambda関数 については、利用者側からは見えません。

CloudTrail に記録されるイベント

CloudTrail に リクエストID が同一の以下3つのイベントがありました。

RotationStarted
May 19, 2023, 17:18:39 (UTC+09:00)

RotateSecret
May 19, 2023, 17:18:39 (UTC+09:00)

RotationSucceeded
May 19, 2023, 17:20:02 (UTC+09:00)

まとめ

Amazon RDS と AWS Secrets Manager の統合を試してみました。
RDS のサービスから管理できるようになり、以前までの仕組みよりもユーザーがシークレットマネージャーを意識することが少なくなりそうです。

余談

怪我から明けて、久々に北八ヶ岳をお散歩してきました。
久しぶりに山を歩く喜びを実感しました。
体力が少し落ちていました。

山本 哲也 (記事一覧)

カスタマーサクセス部のエンジニア(一応)

好きなサービス:ECS、ALB

趣味:トレラン、登山(たまに)