NTTドコモR&Dの技術ブログです。

AWS CDKを用いたRDSのマスターユーザーパスワードの設定方法とmasterUserSecretについて

はじめに

この記事はドコモR&D Advent Calender 2024の25日目の記事です。

はじめまして。NTTドコモサービスイノベーション部ビッグデータ基盤担当の中村です。 普段の業務では、ドコモが保有するビッグデータの利活用を推進するためのビッグデータ基盤の運用や開発に携わっています。本基盤では多くのクラウドサービスを活用していますが、私個人としてはその中でもAWSに触れる機会が最も多いです。

本記事では、私自身が混乱した内容であるAWS CDKでRDSを実装する際のマスターユーザーパスワードの設定方法を紹介します(3章)。また、マスターユーザーパスワードに関連する項目ではあるものの、設定する必要のない項目の使い方といくつかの検証を紹介します(4章)。




1. 本記事における前提

  • AWSのベストプラクティスに則った設定方法以外も紹介しています

AWSが示すベストプラクティスに則った設定方法はもちろんですが、その他の設定方法についても紹介します。また、本記事は2024/12/25時点での情報ですので、ご注意いただければと思います。

  • CDKのレイヤー1, Typescriptを用いています

AWS CDKには異なる3つのレイヤーがありますが、細かい制御が可能であり業務でも使用しているレイヤー1を用いて説明しています。また、本記事中のコードはtypescriptで実装したものとなります。



2. マスターユーザーパスワードに関連する設定項目

AWS RDSにおけるマスターユーザーとは、データベース作成時に指定する管理用ユーザーであり、そのパスワードがマスターユーザーパスワードです。そのため、RDSを構築する際にはマスターユーザーパスワードを設定する必要があります。

RDS作成画面をAWS マネジメントコンソールで確認してみると、以下のようにいくつかの選択肢が用意されていることがわかります。

RDS作成画面

具体的にはRDSの作成と同時にAWS管理(Secrets Manager)のパスワードを生成し、そのパスワードがRDSのマスターユーザーパスワードとして自動で設定される方法があり、この方法がベストプラクティスとされています。 また、セルフマネージドとして実装者がマスターユーザーパスワードの文字列を指定して設定することも可能です。

もちろんCDKでも同様の選択肢があり、CDKの場合は以下2つがマスターユーザーパスワードに関連するプロパティです。

プロパティ 概要 必須か
masterUserPassword 任意の文字列でパスワードを設定 string 任意
manageMasterUserPassword AWS管理のパスワードを設定 boolean 任意

上記2つのうちどちらかを設定する必要があり、どちらも設定しない場合はRDSを構築することができません。

3章では実際にmasterUserPasswordもしくはmanageMasterUserpasswordを使用したマスターユーザーパスワードの設定方法を紹介します。

上記2つのプロパティでマスターユーザーパスワードを設定できると述べましたが、公式ドキュメント見てみるとmasterUserSecretといういかにもマスターユーザーに関係しそうなプロパティがあります。

先に結論をいうと、masterUserSecretはマスターユーザーパスワード自体の設定には必要ありません。ただ、関連する項目ではありますので、4章でmasterUserSecretの使い方といくつかの検証について紹介します。

公式ドキュメント: class CfnDBInstance (construct) · AWS CDK



3. マスターユーザーパスワードの設定方法

3.1. manageMasterUserPassword(ベストプラクティス)

本手法はベストプラクティスであり、RDSのマスターユーザーパスワードをAWS Secrets Managerで管理する方法です。

manageMasterUserPasswordをtrueとすることで、RDSが作成されると同時にパスワードが生成され、そのパスワードはSecrets ManagerのSecretsとして管理されます。また、そのSecretsがRDSのマスターユーザーパスワードとなります。以下は設定例です。

manageMasterUserPassword: true,

AWSマネジメントコンソールのRDS/データベース/[データベース名]/設定のマスター認証情報ARNから設定されたSecrets ManagerのSecretsが確認できます。

注意点としては、masterUserPasswordとの併用ができない点です。manageMasterUserPasswordをtrueとした上で、masterUserPasswordを指定した場合は以下のエラーが出ます。

MasterUserPassword and ManageMasterUserPassword are mutually exclusive. Specify only one of these parameters.
3.2. masterUserPassword

マスターユーザーパスワードを実装者自身が設定する方法です。masterUserPasswordに任意の文字列を設定することで、その文字列がマスターユーザーパスワードとなります。以下は設定例です。

masterUserPassword: "password",
manageMasterUserPassword: false, //もしくは書かない

masterUserPasswordを設定するにはmanageMasterUserPasswordをfalseもしくは設定しない必要があります。

注意点として、本設定方法はパスワードをハードコードすることになり、セキュリティリスクが高まります。

3.3. masterUserPasswordでハードコードしない方法

3.2ではmasterUserPasswordでマスターユーザーのパスワードを設定しましたが、ハードコードしなければいけないという課題がありました。

ここでは、Secrets ManagerのSecretsとmasterUserPasswordを組み合わせることで、ハードコードせずに独自のパスワード(既存のSecrets)を設定する方法を紹介します。以下は設定例です。

const secretParam = secret.Secret.fromSecretNameV2(scope, "secretParam", "SMADTest");

this.rdsTest = new rds.CfnDBInstance(scope, "rdsTest", {
  masterUsername: "password",
  masterUserPassword: secretParam.secretValueFromJson("password").unsafeUnwrap().toString(),
  manageMasterUserPassword: false,
});

上記コードについて簡単に解説すると、まずSecret.fromSecretNameV2でSecrets Managerに設定されているSecretsを参照しています。今回の例の場合、SMADTestというSecretsを参照するよう設定しています。secretValueFromJson(“password”)で、指定したSecrets(SMADTest)のpasswordキーの値を取得しています。また、unsafeUnwrap().toString()でセキュアなデータをstring型に変換しています。

このように設定することで、Sectets Managerで管理した独自のSecretsを使用することができます。 ただし注意点として、unsafeUnwrapを使用することでセキュアなSecretsの値が平文として扱われるため、運用方法によってはログ等に出力されてしまうリスクがあります。


本章では、マスターユーザーパスワードの設定方法をいくつか紹介しました。基本的にはベストプラクティスに則ったmanageMasterPasswordを設定する方法が推奨されますが、要件や状況に合わせて3.2や3.3の方法を使用する場面もあるかと思います。



4. 設定不要な項目(masterUserSecret)

本章では、マスターユーザーパスワード自体の設定には関連しないプロパティであるmasterUserSecretの使い方といくつかの検証を紹介します。

4.1. masterUserSecretの使い方

再度になりますが、masterUserSecretはマスターユーザーパスワードに関連するではありますが、パスワード自体を指定するためのプロパティではありません。

masterUserSecretにはkmsKeyIdとsecretArnという2つのプロパティがありますが、それぞれの使い方についての結論からお伝えすると

kmsKeyId: 必要に応じて設定する

secretArn: 設定しない

です。

kmsKeyIdについては、Secretsの暗号化に使用するKms Keyを指定するためのプロパティです。

マスターユーザーパスワードをSecrets Managerで管理している場合、つまりmanageMasterUserPasswordをtrueとしている場合に設定可能となります。manageMasterUserPasswordを設定せずにkmsKeyIdを指定する場合、以下のエラーが出ます。

A ManageMasterUserPassword value is required when MasterUserSecretKmsKeyId is specified.


続いてsecretArnについてですが、設定する必要はありません。

secretArnはAWS管理のマスターユーザーパスワードが格納されているSecretsのARNを取得するためのプロパティです。つまり、manageMasterUserSecretがtrueの場合、masterUserSecret.secretArnを参照することでSecretsのARNが得られます。RDSとは別のリソースがマスターユーザーとしてRDSに接続したい場合に使用します。

4.2では、secretArnの使用方法についての上記理解が正しいことを示すために行なったいくつかの検証結果を紹介します。

4.2. masterUserSecretについての誤解と検証

本節では、マスターユーザーパスワードを設定する際に私自身が詰まった理由でもあるmasterUserSecretについての誤解といくつかの検証を紹介します

まずはじめに公式ドキュメントを読んだ時、masterUserSecretとは既存のSecretsをマスターユーザーパスワードとして設定するためのプロパティだと思いました。このような考えから、masterUserSecretのsecretArnに既存のSecretsのARNを設定してデプロイしてみたところ以下のエラーが出ました。

masterUserSecret: {
    kmsKeyId: "KMSのKeyID",
    secretArn: "arn:aws:secretsmanager:ap-northeast-1:[accountID]:secret:[xxxxxxx]", //既存のSecretsのARN
}
MasterUserPassword must be provided when ManageMasterUserPassword is set to false. 

これによりmasterUserPasswordもしくはmanageMasterUserPasswordを設定する必要があること、masterUserSecretではパスワードを設定できないことがわかりました。

では、masterUserSecretとは何に使われるプロパティなのかということで、再度masterUserSecret.secretArnのドキュメントを確認したところ以下の記載がありました。

The Amazon Resource Name (ARN) of the secret.

This parameter is a return value that you can retrieve using the Fn::GetAtt intrinsic function.

masterUserSecretのsecretArnはSecretsのARNであり、返り値とのことです。ここで、RDSのマスターユーザーパスワードが格納されたSecretsのARNを返すプロパティであるという理解をしました。

ですが確信は得られていなかったので、実際にsecretArnによってSecretsのARNを取得できるのかを検証しました。具体的には、manageMasterUserPasswordをTrueに設定し、materUserSecretの値をgetAttで取得したところAWS管理のSecretsのARNを示しました。

また、以下のようにmasterUserSecretのsecretArnに既存のSecretsのARNを設定した上で、manageMasterUserPasswordをTrueにした場合でも、getAttでmasterUserSecret.secretArnを取得するとAWS管理のSecretsが得られました。

manageMasterUserPassword: true, //自動生成される
masterUserSecret: {
    kmsKeyId: "KMSのKeyID",
    secretArn: "arn:aws:secretsmanager:ap-northeast-1:[accountID]:secret:[xxxxxxx]", //既存のSecretsのARN
}

また、masterUserPasswordでパスワードを設定し、masterUserSecret.secretArnには既存のSecretsのARNを設定した場合に、getAttでsecretArnを取得しようとしたところ以下のエラーが出ました。

Attribute 'MasterUserSecret.SecretArn' does not exist


これらの結果より、secretArnは設定する必要がなく、Secrets Managerで管理されたSecretsのARNを参照するためのプロパティということが分かりました。



5. まとめ

ここまで読んでいただきありがとうございました。

本記事ではAWS CDKを用いたRDSのマスターユーザーパスワードを設定する方法と関連するプロパティについて紹介しました。結論としては

・manageMasterUserPasswordを使用する方法がベストプラクティス

・場合によってはmasterUserPasswordを使用

・masterUserSecretのsercretArnは設定しない

・masterUserSecret.secretArnはAWS管理のSecretsのARNを取得するためのプロパティ

です。

レイヤー1のCDKでRDSを構築する際のマスターユーザーパスワードについて、というかなりニッチな部分を取り上げましたが、私と同じように混乱した方の参考になれば幸いです。

メリークリスマス🎅



6. 参考

【1】class CfnDBInstance (construct) · AWS CDK

【2】Amazon RDSとAWS Secrets Manager の統合に伴うCloudFormationの新プロパティの設定を解説

【3】AWS CDKでAmazon Aurora DB クラスターとAWS Secrets Managerとの統合を設定してみた | DevelopersIO