🔐

RDSのマスターユーザーパスワードを自動ローテーションさせる

2023/12/20に公開

この記事は terraform Advent Calendar 2023 の 20日目(シリーズ2)の記事です。

実施のきっかけ

マスターユーザーのパスワードをローテーションさせるというチケットが長く塩漬けになっていたところに、この記事に出会いました。

https://tech.isid.co.jp/entry/terraform_manage_master_user_password

この記事により、Secrets Managerへの保存とローテーションを自動化できるようになっていた(2022/12)ことを知りました。

https://aws.amazon.com/jp/about-aws/whats-new/2022/12/amazon-rds-integration-aws-secrets-manager/

Amazon RDS は、RDS データベースインスタンスのマスターユーザーパスワードの管理方法を合理化するため、AWS Secrets Manager との統合をサポートするようになりました。

AWS provider v4.61.0

v4.61.0(2023/05/31)以降のAWS providerでSecrets Managerとの統合が利用できるようになります。

https://github.com/hashicorp/terraform-provider-aws/releases/tag/v4.61.0

  • resource/aws_db_instance: Add manage_master_user_password, master_user_secret and master_user_secret_kms_key_id arguments to support RDS managed master password in Secrets Manager (#28848)
  • resource/aws_rds_cluster: Add manage_master_user_password, master_user_secret and master_user_secret_kms_key_id arguments to support RDS managed master password in Secrets Manager (#28848)

リリースノートからのコピペですが、master_user_secretは正しくはargumentではなくattributeです(後で使います)。

AWS provider v5.22.0

v5.22.0(2023/10/20)ではスナップショットまたはポイントインタイムリカバリからの復元によって作成したaws_db_instancemanage_master_user_passwordが効かない問題が修正されています(aws_rds_clusterではこの問題は発生していません)。

https://github.com/hashicorp/terraform-provider-aws/releases/tag/v5.22.0

https://github.com/hashicorp/terraform-provider-aws/pull/33699

既存のaws_rds_clusterでmanage_master_user_passwordを有効にする

マスターユーザーはアプリケーションや運用で(一つの例外を除き)使っていないため、さくっと有効化します。

有効化の前にtfstateを覗く

master_passwordに平文でパスワードが書かれていました。

state-before

有効化する

master_password argumentを削除してmanage_master_user_password = trueを追加するだけです。

有効化した後にtfstateを覗く

最初からmanage_master_user_password = trueで作成するとmaster_passwordはnullになるようですが、途中で切り替えるとtfstateにはパスワードが書かれたままになります。
すでに新しいパスワードがSecrets Managerに保存されているため、このパスワードはもう使えません。

state-after

Secrets Managerを確認

RDSコンソールのConfigurationタブからSecrets Managerに飛べます。

7日でローテーションするようになっています。

ローテーションの周期

https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/rds-secrets-manager.html#rds-secrets-manager-overview

Aurora はシークレットの設定を管理し、デフォルトではシークレットを7日ごとにローテーションします。ローテーション スケジュールなど、一部の設定を変更できます。

ModifyDBClusterなどのAPIにはこれを制御するパラメータはないため、「一部の設定を変更」はSecretを直接編集することによって可能になります。

https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_ModifyDBCluster.html

Secrets Managerに保存されたパスワードをMySQL providerで使う

唯一の例外としてMySQL providerの動作にはマスターユーザーを利用していました。
HashiCorpのMySQL providerがアーカイブされてからは非公式forkを利用しています。

https://github.com/petoju/terraform-provider-mysql

以前はパラメータストアにマスターユーザーのパスワードを保存し、dataで参照していました。
自前で用意したパラメータのためnameで簡単にdataを取得できていましたが、RDSとの統合により自動作成されたSecretの名前やARNは事前には予測できません。

そのため、aws_rds_clusterattributeからSecretのARNを入手することになります。
その際master_user_secret.secret_arnではなく master_user_secret[0].secret_arn とする必要があります。

provider "mysql" {
  endpoint = "${local.mysql_host}:${var.mysql_port}"
  username = jsondecode(data.aws_secretsmanager_secret_version.master_password.secret_string)["username"]
  password = jsondecode(data.aws_secretsmanager_secret_version.master_password.secret_string)["password"]
}

variable "mysql_port" {
  type        = number
}

data "aws_rds_cluster" "this" {
  cluster_identifier = local.cluster_identifier
}

data "aws_secretsmanager_secret" "master_password" {
  arn = data.aws_rds_cluster.this.master_user_secret[0].secret_arn
}

data "aws_secretsmanager_secret_version" "master_password" {
  secret_id = data.aws_secretsmanager_secret.master_password.id
}

AWS API的には複数存在することはなさそうですが、

https://github.com/aws/aws-sdk-go/blob/394d04f7e36b85532cede3eb815a6a23413b2eaa/service/rds/api.go#L26834

https://github.com/hashicorp/terraform-provider-aws/blob/91e190128b0c476411215ba1fae6425de5a9bfaf/internal/service/rds/cluster.go#L1174-L1175

attributeのtypeはlistになっているため、master_user_secret[0]とする必要がありました。

https://github.com/hashicorp/terraform-provider-aws/blob/91e190128b0c476411215ba1fae6425de5a9bfaf/internal/service/rds/cluster.go#L277-L278

これはどうも型の選択肢の都合でそうなっているみたいです。

https://developer.hashicorp.com/terraform/plugin/sdkv2/schemas/schema-types

https://github.com/hashicorp/terraform-plugin-sdk/blob/f3f8b0791224809d2d7ce6942fddde57ab686bd1/helper/schema/valuetype.go#L15-L22

(typeObjectは非公開)

https://github.com/hashicorp/terraform-plugin-sdk/blob/f3f8b0791224809d2d7ce6942fddde57ab686bd1/helper/schema/valuetype.go#L23

Discussion