terraformでRDSのパスワードをSystem Managerから参照して使う
背景
terraformでRDSを作るときにユーザー名,パスワードが必須となります.しかし直書きはしたくありません.ググってみると,.tfvarsを使ったりの方法があったのですが,何が何でもローカルファイルにパスワードを書きたくねぇ..
仮のパスワードを設定して作成後に変更という方法もあったのですが,仮パスワードも書きたくねぇ..(もはや意地)
そう考えて,System Managerから参照する方法について考えてみました.
手順としては下記になります.
①System Managerのパラメータストアに機密データを登録
②System Managerのパラメータストアから機密データ取得して
③terraform applyの引数で②で取得できた情報を渡す
環境
terraform version 1.1.8
terraform aws provider version 4.9.0
今回試したソースコード
RDSの機密データをSystem Managerのパラメータストアに登録
タイプは安全な文字列に指定してデータベース名,ユーザー名,パスワードの3つの機密データを登録しておきます.
/dev/db/database_name
/dev/db/username
/dev/db/password
登録したパラメータをCLIで取得できるか確認します.
※レスポンスのXXXXX
の部分はマスクしています.
$ aws ssm get-parameters --name "/dev/db/database_name" --region=us-west-1
{
"Parameters": [
{
"Name": "/dev/db/database_name",
"Type": "SecureString",
"Value": "XXXXX",
"Version": 1,
"LastModifiedDate": XXXXX,
"ARN": "arn:aws:ssm:us-west-1:XXXXX",
"DataType": "text"
}
],
"InvalidParameters": []
}
これができたら,パラメータストアからの取得は問題なしです.
あとは"Value"
を使いたいのですが,上記のままだと暗号化されてしまっているので--with-decryption
オプションをつけて,
レスポンスの"Value"
のところだけほしいので| jq -r ".Parameters[].Value"
として必要なものだけ取り出します.
$ aws ssm get-parameters --name "/dev/db/database_name" --region=us-west-1 --with-decryption | jq -r ".Parameters[].Value"
[登録したデータベース名]
これでデータベース名をパラメータストアから取得できました.ユーザー名とパスワードも取得できることを確認しておきます.
$ aws ssm get-parameters --name "/dev/db/username" --region=us-west-1 --with-decryption | jq -r ".Parameters[].Value"
[登録したユーザー名]
$ aws ssm get-parameters --name "/dev/db/password" --region=us-west-1 --with-decryption | jq -r ".Parameters[].Value"
[登録したパスワード]
terraformを書いていく
構成は次のとおりです.本当はサブネットやVPCなども作成したほうが良いのですが,今回は必要最低限のものだけにしました.
.
├── app
│ ├── locals.tf
│ └── main.tf
└── modules
└── rds
├── main.tf
└── varriable.tf
# コマンドライン引数から取得
variable "database_name" {}
variable "db_master_username" {}
variable "db_master_password" {}
provider "aws" {
region = "us-west-1"
default_tags {
tags = {
System = local.name_prefix
Owner = "lightkun"
}
}
}
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.9.0"
}
}
required_version = "1.1.8"
backend "s3" {
bucket = "[S3バケット名]"
key = "dev.tfstate"
region = "us-west-1"
}
}
module "rds" {
source = "../modules/rds"
name_prefix = local.name_prefix
db_az = [local.az_1a, local.az_1b]
database_name = var.database_name
db_master_username = var.db_master_username
db_master_password = var.db_master_password
db_num = 2
instance_class = "db.t3.small"
}
locals {
name_prefix = "rds_tf"
env = "dev"
az_1a = "us-west-1a"
az_1b = "us-west-1b"
}
resource "aws_rds_cluster" "cluster" {
cluster_identifier = "aurora-cluster"
engine = "aurora-mysql"
engine_version = "5.7.mysql_aurora.2.03.2"
availability_zones = var.db_az
database_name = var.database_name
master_username = var.db_master_username
master_password = var.db_master_password
preferred_backup_window = "07:00-09:00"
skip_final_snapshot = true
}
resource "aws_rds_cluster_instance" "cluster_instances" {
count = var.db_num
identifier = "aurora-cluster-${count.index + 1}"
cluster_identifier = aws_rds_cluster.cluster.id
instance_class = var.instance_class
engine = aws_rds_cluster.cluster.engine
engine_version = aws_rds_cluster.cluster.engine_version
}
variable "name_prefix" {}
variable "db_az" {}
variable "database_name" {}
variable "db_master_username" {}
variable "db_master_password" {}
variable "db_num" {}
variable "instance_class" {}
実行
terraformを実行してrdsを作成していきます.引数ではパラメータストアの値を渡します.
$ cd app/
$ terraform init
$ terraform apply \
-var=database_name=`aws ssm get-parameters --name "/dev/db/database_name" --region=us-west-1 --with-decryption | jq -r ".Parameters[].Value"` \
-var=db_master_username=`aws ssm get-parameters --name "/dev/db/username" --region=us-west-1 --with-decryption | jq -r ".Parameters[].Value"` \
-var=db_master_password=`aws ssm get-parameters --name "/dev/db/password" --region=us-west-1 --with-decryption | jq -r ".Parameters[].Value"` \
--parallelism=30
成功!
ちなみに,僕愛用のfish shellだと上記の書き方のterraform apply
がエラーになってしまうので,bashで動かしました.
terraform apply
実行時の差分に正しくデータベース名とユーザー名を設定できているか確認できます.パスワードは (sensitive value) となっていて表示されません.
...
+ database_name = "[登録したデータベース名]"
...
+ master_username = "[登録したユーザー名]"
...
作成後,(terraformで管理してないですが)Cloud9を起動して,セキュリティグループを作成・アタッチしてRDSにアクセスできることを確認しました.
デメリット
ローカルでは機密データの情報を記述しませんが,S3の.tfstateには平文で保存されてしまいます.これはなんともできないか...
参考資料
Discussion