Open4

TerraformでAuroraを作成する際にセキュアにパスワードを設定したい

bun913bun913

問題の概要

TerraformでAWSのAuroraをプロビジョニングしたい。

その際に、DB接続用のマスターパスワードを設定する必要があるが、例えば以下のようにランダムパスワードを生成する。

resource "random_password" "password" {
  length           = 16
  special          = true
  override_special = "_%@"
}

terraform.tfstate ファイルには以下のように生成結果がプレーンテキストで出力されてしまっている。

  "resources": [
    {
      "mode": "managed",
      "type": "random_password",
      "name": "password",
      "provider": "provider[\"registry.terraform.io/hashicorp/random\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "id": "none",
            "keepers": null,
            "length": 16,
            "lower": true,
            "min_lower": 0,
            "min_numeric": 0,
            "min_special": 0,
            "min_upper": 0,
            "number": true,
            "override_special": "_%@",
            "result": "${ここにランダム生成したパスワードが出力されている}",
            "special": true,
            "upper": true
          },
          "sensitive_attributes": [],
          "private": "bnVsbA=="
        }
      ]
    }
  ]

tfstate自体秘匿情報なのでS3でアクセス制御をかけるのは当然だが、そもそもtfstateにパスワードが残っていても問題がないようにしたい。

参考

https://techlife.cookpad.com/entry/2020/02/28/120000

bun913bun913

方向性

大まかに以下の方向で行こうかと検討

  • あらかじめ シークレットマネージャーに設定するパスワードを生成しておく
    • ↑これはTerraformではなく手動で作っておく
  • terraform でAuroraクラスターを作成する際には、ダミーパスワードを使用する
    • RDSのプロビジョニングの後に terraformの provisioner local-exec により aws-cliでシークレットマネージャーの値を参照して、その値にパスワードをセットしする
    • ↑のようにすれば インフラ構築後に諸々セットアップできるし、tfstateにはパスワード情報が残らないのでは
bun913bun913

メモ

  • 事前にパラメーターストアを準備
    • 今回はパスワードローテーションまでを要しないためパラメーターストアで用意(ローテーションが必要ならシークレットマネージャーを利用)
    • tfstateにもシークレット情報を残したくないので これは terraform外で作成(terraformないで作成しない。当たり前だがすでにパラメーターストアがある状態でtfで作成しようとすると already exitsと怒られる)
  • RDSへの接続を確かめるために、 踏み台EC2インスタンスを作成する
    • 踏み台といっても、プライベートサブネットに配置し、session managerで接続すること
bun913bun913

以下のようにして rds_clusterが作成されたタイミングで local-exec によるDBパスワードの変更を行う

# clusterのパスワードを変更する
resource "null_resource" "cluster" {
  # DBが作成されたことをトリガーにする
  triggers = {
    cluster_instance_ids = aws_rds_cluster.main.id
  }
  provisioner "local-exec" {
    # aws cliでRDSのパスワードを変更する
    command    = "aws ssm get-parameter --name /${var.project}/db_password --query 'Parameter.Value' --with-decryption | xargs -IPASS aws rds modify-db-cluster --db-cluster-identifier ${aws_rds_cluster.main.id} --master-user-password PASS"
    on_failure = fail
  }
}

これにより プライベートサブネット上の EC2インスタンスからセキュアなパスワードで接続できた