俺です。
世界70億のterraform職人の皆様こんばんは。teraform職人の夜は遅いですね。
さてmodule使ってますか?
最近といってもつい数時間前から今まで自分が作ったterraform tfファイルのリファクタリングを始めました。
※同じ組織の方はGHEにpushしてるorenoシリーズリポジトリみてね(業務連絡)
今回はIAM Userとpolicyをmodule化して、
楽々使いまわせるようにする例を載せちゃいます。
参考というかこたえ
terraformのcommunity-moduleリポジトリがあるのでズバリこれで。
https://github.com/terraform-community-modules
さてやってみましょー
moduleの作成
moduleとなるterraform tfファイルを作ります
例として以下の様なディレクトリ/ファイル構成にしておきます。
1tfにまとめてもいいんじゃねって思うのですが
まあーresourceはながーくなることもあるし、community-modulesがこんな感じになってるので
この辺は準拠しておいたほうがよさそうな感じですかねー。
各プロジェクトでルール作ってしまえば良いと思いますね。
moduleのファイル用途
ファイル名 | 用途 |
---|---|
variables.tf | 変数定義 |
iam_***.tf | resource定義 |
outputs.tf | 戻り値定義 |
moduleのディレクトリ/ファイル構造
orenomac$ tree module/iam
module/iam
├── group
│ ├── iam_group.tf
│ ├── outputs.tf
│ └── variables.tf
├── policy
│ ├── aws_iam_policy.tf
│ ├── outputs.tf
│ └── variables.tf
├── role
└── user
├── aws_iam_user.tf
├── outputs.tf
└── variables.tf
IAM Group用モジュールを作る
- variables.tf
module resourceの引数に指定するvariableを定義します。
variable "aws_iam_groupname" {
description = "iam group name"
}
variable "aws_iam_grouppath" {
description = "iam group path(/users/)"
default = "/"
}
- iam_group.tf
moduleで動作するresourceを定義します
resource "aws_iam_group" "iam-group" {
name = "${var.aws_iam_groupname}"
path = "${var.aws_iam_grouppath}"
}
- outputs.tf
module外から参照されるresourceでmodule内で定義された変数を参照するための戻り値を定義します。
outputを定義しておかないと、moduleで作られたresource内variableを、外部resourceで参照することができません。
output "name" {
value = "${aws_iam_group.iam-group.name}"
}
IAM User用モジュールを作る
- variables.tf
variable "aws_iam_username" {
description = "iam user name"
}
variable "aws_iam_grouppath" {
description = "iam group path(/users/)"
default = "/"
}
- aws_iam_user.tf
resource "aws_iam_user" "iam-user" {
name = "${var.aws_iam_username}"
path = "${var.aws_iam_grouppath}"
}
- outputs.tf
output "name" {
value = "${aws_iam_user.iam-user.name}"
}
IAM Policy用モジュールを作る
- variables.tf
variable "aws_iam_policy_name" {
description = "Policy Name"
default = "iam-policy"
}
variable "aws_iam_policy_path" {
description = "iam policy path"
default = "/policy/"
}
variable "aws_iam_policy_description" {
description = "iam policy description"
default = "iam policy"
}
variable "aws_iampolicy_json" {
description = "iampolicy json filename"
default = "iam_policy.json"
}
- aws_iam_policy.tf
policyにはjsonファイルをそのまま放り込めるように組み込み関数fileを使います。
resource "aws_iam_policy" "iam-policy" {
name = "${var.aws_iam_policy_name}"
path = "${var.aws_iam_policy_path}"
description = "${var.aws_iam_policy_description}"
policy = <<EOF
${file("${var.aws_iampolicy_json}")}
EOF
}
- outputs.tf
arnを返すようにします。
output "name" {
value = "${aws_iam_policy.iam-policy.name}"
}
output "arn" {
value = "${aws_iam_policy.iam-policy.arn}"
}
moduleを利用するtfの作成
こんなかんじです
orenomac$ tree examples/
examples/
├── datawanwan_policy.json
└── test_terraform.tf
- test_terraform.tf
メインとなるtfではmoduleに変数指定して呼び出すだけです。
sourceには使用するmoduleが格納されているディレクトリまでのパスを記述します。
本例ではディレクトリパスを指定してますが、github/bitbucketなどのパスを指定することもできます。
同僚の皆様GHEにpushしとくので使って下さいww(業務連絡
provider "aws" {
region = "ap-northeast-1"
}
module "iam-group" {
source = "../module/iam/group"
aws_iam_groupname = "oreore"
aws_iam_grouppath = "/oreore/"
}
module "iam-user" {
source = "../module/iam/user"
aws_iam_username = "iam-user"
aws_iam_grouppath = "/oreore/users/"
}
module "iam-datawanwan" {
source = "../module/iam/user"
aws_iam_username = "iam-datawanwan"
aws_iam_grouppath = "/oreore/users/"
}
module "iam-datawanwan_policy" {
source = "../module/iam/policy/"
aws_iam_policy_name = "datawanwan"
aws_iam_policy_path = "/policy/"
aws_iam_policy_description = "datawanwan policy"
aws_iampolicy_json = "datawanwan_policy.json"
}
/* moduleで定義されたresourceのvariablesを外部resourceから参照する例 */
resource "aws_iam_policy_attachment" "datawanwan" {
name = "datawanwan"
users = ["${module.iam-datawanwan.name}"]
policy_arn = "${module.iam-datawanwan_policy.arn}"
}
- datawanwan_policy.json
datadogのドキュメントに書いてる通りのポリシーを準備しておきます。
module
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"autoscaling:Describe*",
"cloudformation:DescribeStacks",
"cloudformation:DescribeStackEvents",
"cloudformation:DescribeStackResources",
"cloudformation:GetTemplate",
"cloudfront:Get*",
"cloudfront:List*",
"cloudtrail:DescribeTrails",
"cloudtrail:GetTrailStatus",
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*",
"dynamodb:GetItem",
"dynamodb:BatchGetItem",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:DescribeTable",
"dynamodb:ListTables",
"ec2:Describe*",
"elasticache:Describe*",
"elasticbeanstalk:Check*",
"elasticbeanstalk:Describe*",
"elasticbeanstalk:List*",
"elasticbeanstalk:RequestEnvironmentInfo",
"elasticbeanstalk:RetrieveEnvironmentInfo",
"elasticloadbalancing:Describe*",
"iam:List*",
"iam:Get*",
"route53:Get*",
"route53:List*",
"rds:Describe*",
"rds:ListTagsForResource",
"s3:List*",
"sdb:GetAttributes",
"sdb:List*",
"sdb:Select*",
"ses:Get*",
"ses:List*",
"sns:Get*",
"sns:List*",
"sqs:GetQueueAttributes",
"sqs:ListQueues",
"sqs:ReceiveMessage"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
いざterraform plan/apply..のまえに
terraform getでmoduleを取得します
orenomac$ cd <path>/<to>/examples
orenomac$ terraform get
Get: file:///orenoterraform/module/iam/group
Get: file:///orenoterraform/module/iam/user
Get: file:///orenoterraform/module/iam/user
Get: file:///orenoterraform/module/iam/policy
plan
planを実行します
orenomac$ terraform plan
Refreshing Terraform state prior to plan...
The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed.
Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.
+ aws_iam_policy_attachment.datawanwan
name: "" => "datawanwan"
policy_arn: "" => "${module.iam-datawanwan_policy.arn}"
users.#: "" => "1"
users.XXXXXXXXXXX: "" => "iam-datawanwan"
+ module.iam-datawanwan_policy.aws_iam_policy.iam-policy
arn: "" => "<computed>"
description: "" => "datawanwan policy"
name: "" => "datawanwan"
..省略..
apply
apply叩く前にACCESS_KEYとSECRET_KEYは設定しておきましょうー。
direnvとか環境変数のexportで。
orenomac$ terraform apply
module.iam-user.aws_iam_user.iam-user: Creating...
arn: "" => "<computed>"
name: "" => "iam-user"
path: "" => "/oreore/users/"
unique_id: "" => "<computed>"
module.iam-datawanwan_policy.aws_iam_policy.iam-policy: Creating...
arn: "" => "<computed>"
..省略..
orenomac$ terraform show
aws_iam_policy_attachment.datawanwan:
id = datawanwan
groups.# = 0
name = datawanwan
policy_arn = arn:aws:iam::XXXXXXXXXXX:policy/policy/datawanwan
roles.# = 0
users.# = 1
users.XXXXXXXXXXXX = iam-datawanwan
ちなみに
moduleのoutputは、terraform outputで参照することはできません。
orenomac$ terraform output
The state file has no outputs defined. Define an output
in your configuration with the `output` directive and re-run
`terraform apply` for it to become available.
みんなterraform module使って楽しましょう的~
完