Terraform ( v0.11.14 ) でSSMパラメータと連携してAurora ( MySQL ) を構築する
- やったこと
- TerraformのSSMパラメータについて
- vpc-id / subnet-id / db-passowd / securit-group-id を参照してサブネットIDを取得する
- Terraformのコード全体
- まとめ
やったこと
の以前に書いたブログ ( Terraformのコードの改善 )
- TerraformでRDSを構築するときにSSMパラメータに登録したパスワードを参照してインスタンスを構築する
- VPC-IDをSSMパラメータから取得する
- SecurityGroupIDをterraformの機能を使って取得する
- サブネットグループのサブネットIDをterraformの機能を使って取得する
- ※ Terraformのバージョンは
0.11.14
を利用した
- ※ Terraformのバージョンは
■ 構築する構成図 (workspace=prod)
以前のブログでTerrfaromをRDSを作成したときは、DBのパスワードを平文でかつterraformのコード内に定義していた。 これは個人開発で環境を構築するのはいいが、チームやGitでコード管理する場合にはセキュリティ的によくない。 この課題を解決するために、今回はAWSのSSMパラメータにKMSで暗号化した状態でパスワードを管理し、Terraformでこの値を参照するように変更する。
TerraformのSSMパラメータについて
- SSMパラメータの機能 ( 登録 / 参照 / 上書き )
vpc-id / subnet-id / db-passowd / securit-group-id を参照してサブネットIDを取得する
■ AWSのSSMパラメータの画面 ( vpc_id
)
※ Stringで保存 ( 本グログには記載していないですが、VPC関連のリソースを作るときにSSMパラメータに自動登録するようにしています )
■ AWSのSSMパラメータの画面 ( db_password
)
※ SecureStringで保存
■ subnet_idの画面
■ SecurityGroup_idの画面
■ ssmパラメータのkeyを指定して値を取得する処理 ( vpc_id )
data "aws_ssm_parameter" "vpc_id"
→ vpc_id
が keyとして指定する。
data "aws_ssm_parameter" "vpc_id" { name = "vpc_id" }
■ RDSで使うsubnet-idを取得する処理 ( NameTagで検索して取得 )
vpc_id
を指定してNameTagを指定して取得する。今回はRDSを構築するサブネット名をdb-c / db-d
としている。"${data.aws_ssm_parameter.vpc_id.value}"
で ssmパラメータの値を取得できる
data "aws_subnet_ids" "db-c" { vpc_id = "${data.aws_ssm_parameter.vpc_id.value}" tags { Name = "db-c" } } data "aws_subnet_ids" "db-d" { vpc_id = "${data.aws_ssm_parameter.vpc_id.value}" tags { Name = "db-d" } }
■ ssmパラメータのkeyを指定して値を取得する処理 ( DBパスワード )
data "aws_ssm_parameter" "db_password" { name = "db_password" }
- DBのパスワード値をssmパラメータから取得は以下のようにした
master_password_enyenv = "${data.aws_ssm_parameter.db_password.value}"
■ RDSで使うsecurity-group-idを取得する処理 ( NameTagで検索して取得 )
data "aws_security_group" "db" { vpc_id = "${data.aws_ssm_parameter.vpc_id.value}" tags { Name = "db" } }
- SecurityGroup-IDをssmパラメータから取得は以下のようにした
vpc_security_group_ids_enyenv = ["${data.aws_security_group.db.id}"]
Terraformのコード全体
■ ディレクトリ構造(一部抜粋)
├── modules │ ├── rds │ │ └── aurora-mysql │ │ └── main.tf ( resource側 ) ├── rds.tf ( module側 ) ├── s3-backend.tf
■ Module側 ( rds.tf )
variable "availability_zone_prod" { default = ["ap-northeast-1c", "ap-northeast-1d"] } variable "availability_zone_stg" { default = ["ap-northeast-1c"] } variable "availability_zone_dev" { default = ["ap-northeast-1c"] } // vpc_idを取得する data "aws_ssm_parameter" "vpc_id" { name = "vpc_id" } // dbサブネットのidを取得する data "aws_subnet_ids" "db-c" { vpc_id = "${data.aws_ssm_parameter.vpc_id.value}" tags { Name = "db-c" } } // dbサブネットのidを取得する data "aws_subnet_ids" "db-d" { vpc_id = "${data.aws_ssm_parameter.vpc_id.value}" tags { Name = "db-d" } } // dbのSecurityGroupのidを取得する data "aws_security_group" "db" { vpc_id = "${data.aws_ssm_parameter.vpc_id.value}" tags { Name = "db" } } // dbパスワードをssmパラメータストアから取得 data "aws_ssm_parameter" "db_password" { name = "db_password" } locals { master_password_anyenv = "${data.aws_ssm_parameter.db_password.value}" vpc_security_group_ids_anyenv = ["${data.aws_security_group.db.id}"] db_subnet_ids_anyenv = ["${data.aws_subnet_ids.db-c.ids}", "${data.aws_subnet_ids.db-d.ids}"] instance_class_prod = "db.r4.large" instance_class_stg = "db.t2.medium" instance_class_dev = "db.t2.medium" vpc_security_group_ids = "${split(",",join(",",local.vpc_security_group_ids_anyenv))}" db_subnet_ids = "${split(",",join(",",local.db_subnet_ids_anyenv))}" availability_zone = "${split(",",(terraform.workspace == "prod" && terraform.workspace != "stg" && terraform.workspace != "dev") ? join(",", var.availability_zone_prod): join(",",var.availability_zone_dev))}" } module "create-aurora-mysql" { source = "./modules/rds/aurora-mysql" description = "for app" cluster_identifier = "app-db-${terraform.workspace}-cluster" identifier = "app-db-${terraform.workspace}" database_name = "app" master_username = "root" engine = "aurora-mysql" engine_version = "5.7.12" db_subnet_group_name = "app_db" db_parameter_group_name = "app-aurora57" db_parameter_group_family = "aurora-mysql5.7" cluster_parameter_group_family = "aurora-mysql5.7" cluster_parameter_group_name = "app-cluster-aurora57" preferred_backup_window_cluster = "20:06-20:36" preferred_maintenance_window_instance = "sun:19:00-sun:19:30" preferred_maintenance_window_cluster = "sun:19:00-sun:19:30" final_snapshot_identifier = true backup_retention_period = 7 auto_minor_version_upgrade = true publicly_accessible = false storage_encrypted = "${terraform.workspace == "prod" ? true : false}" master_password = "${local.master_password_anyenv }" vpc_security_group_ids = "${split(",",join(",",local.vpc_security_group_ids_anyenv))}" db_subnet_ids = "${split(",",join(",",local.db_subnet_ids))}" instance_class = "${terraform.workspace == "prod" ? local.instance_class_prod : terraform.workspace == "stg" ? local.instance_class_stg :local.instance_class_dev }" availability_zone = "${split(",",(terraform.workspace != "prod" && terraform.workspace == "stg" && terraform.workspace != "dev") ? join(",", var.availability_zone_stg): join(",",local.availability_zone))}" }
■ Resource側 ( main.tf )
variable "instance_class" {} variable "description" {} variable "identifier" {} variable "cluster_identifier" {} variable "database_name" {} variable "master_username" {} variable "master_password" {} variable "db_parameter_group_name" {} variable "db_parameter_group_family" {} variable "cluster_parameter_group_name" {} variable "cluster_parameter_group_family" {} variable "preferred_backup_window_cluster" {} variable "preferred_maintenance_window_cluster" {} variable "preferred_maintenance_window_instance" {} variable "final_snapshot_identifier" {} variable "backup_retention_period" {} variable "auto_minor_version_upgrade" {} variable "publicly_accessible" {} variable "storage_encrypted" {} variable "engine" {} variable "engine_version" {} variable "db_subnet_group_name" {} variable "availability_zone" { default = [] } variable "vpc_security_group_ids" { default = [] } variable "db_subnet_ids" { default = [] } resource "aws_rds_cluster" "aurora_cluster" { cluster_identifier = "${var.cluster_identifier}" availability_zones = ["${var.availability_zone}"] database_name = "${var.database_name}" engine = "${var.engine}" master_username = "${var.master_username}" master_password = "${var.master_password}" db_cluster_parameter_group_name = "${var.cluster_parameter_group_name}" db_subnet_group_name = "${aws_db_subnet_group.default.name}" vpc_security_group_ids = ["${var.vpc_security_group_ids}"] preferred_backup_window = "${var.preferred_backup_window_cluster}" preferred_maintenance_window = "${var.preferred_maintenance_window_cluster}" final_snapshot_identifier = "${var.final_snapshot_identifier}" backup_retention_period = "${var.backup_retention_period}" storage_encrypted = "${var.storage_encrypted}" } resource "aws_rds_cluster_instance" "cluster_instances" { count = "${length(var.availability_zone)}" identifier = "${var.identifier}-${count.index+1}" cluster_identifier = "${aws_rds_cluster.aurora_cluster.id}" instance_class = "${var.instance_class}" engine = "${var.engine}" db_subnet_group_name = "${aws_db_subnet_group.default.name}" db_parameter_group_name = "${var.db_parameter_group_name}" auto_minor_version_upgrade = "${var.auto_minor_version_upgrade}" publicly_accessible = "${var.publicly_accessible}" preferred_maintenance_window = "${var.preferred_maintenance_window_instance}" } resource "aws_db_subnet_group" "default" { name = "${var.db_subnet_group_name}" subnet_ids = ["${var.db_subnet_ids}"] description = "${var.description}" } resource "aws_db_parameter_group" "default" { name = "${var.db_parameter_group_name}" family = "${var.db_parameter_group_family}" description = "${var.description}" } resource "aws_rds_cluster_parameter_group" "default" { name = "${var.cluster_parameter_group_name}" family = "${var.cluster_parameter_group_family}" description = "${var.description}" }
まとめ
今回は以下のことに取り組んだ。
- VPC-IDをSSMパラメータから取得
- DBのパスワードをSSMパラメータから取得
- DBのサブネットIDをTerraformの機能を使って検索して取得
- DBのセキュリティグループIDをTerraformの機能を使って検索して取得
SSMパラメータをTerraformで利用することで機密性の高いデータを扱うことができるようになった。 また、AWSリソース情報をフィルタして取得して利用することで動的な書き方が可能になりました。