はじめに
友人と飲みに行った際のトイレで IAM ロールの module の良い構築方法を思いついたので IAM ロールの module を作ることに。
何気ない時にぱっと思いついた案が採用されることってありますよね。。
バージョンは以下の通り。
このバージョン以外での動作は確認してません。
terraform {
required_version = "1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "5.3.0"
}
}
}
GitHubにソースコードを上げておりますので、もしよろしければ参考に。
⇒ こちらをクリック
参考にしていただくためにGitHubに残しております。
いかなる損失が発生しても一切責任は負いませんのでよろしくお願いしますね。
また、今回は別の s3 の module も使用しております。
それに関する記事は、こちらをクリック
module
IAM ロールと IAM ポリシー作成用の module について説明していきます。
そんなに複雑なことはやっていないです。
記事が長くなるので一部抜粋して説明していきます。
コードは GitHub からご確認を。
variables.tf
まずは変数ファイルから。
基本的にはシンプルですが、唯一ややこしいのはこれ。
variable "policy_statement" {
type = list(object({
effect = string # Allow もしくは Deny
actions = list(string) # 許可 もしくは 拒否するアクションのリスト
resources = list(string) # 対称のリソースのリスト。バケットARN以降の文字列を指定。
condition = list(object({
test = string # 評価する IAM 条件演算子の名前
variable = string # 条件を評価する値
values = list(string) # 条件を適用するコンテキスト変数の名前
}))
}))
default = []
description = "IAMポリシーステートメントのリスト"
}
どのような値を渡せばいいかは、module 呼び出し元の説明にて記載します。
effect
, actions
, resources
は後述するリソース作成時に必須のパラメータになるので、適切な値を渡す必要があります。
逆にcondition
に関しては設定しなくてもよいので、condition = []
とすれば設定されません。
main.tf
outputs.tf に関しては説明不要ですので、次は main.tf について。
main.tfでは IAM ロールと IAM ポリシーの両方を作成しているので分けて説明します。
まずは IAM ポリシーから。
data "aws_iam_policy_document" "this" { ※1
dynamic "statement" {
for_each = var.policy_statement
content {
effect = statement.value.effect
actions = statement.value.actions
resources = statement.value.resources
dynamic "condition" {
for_each = statement.value.condition ※2
content {
test = condition.value.test
variable = condition.value.variable
values = condition.value.values
}
}
}
}
}
resource "aws_iam_policy" "this" {
name = local.policy_name
description = var.policy_description
policy = data.aws_iam_policy_document.this.json ※3
tags = {
Name = local.policy_name
}
}
※1
data "aws_iam_policy_document" "this" { }
data ソースを使用して IAM ポリシーのドキュメントを作成しております。
公式ページ ⇒ Data Sources
Terraform 実行対象の AWS アカウントやリージョン、または既存リソースのパラメータ取得など、
data ソースを使用することで様々なことが出来ますので是非身につけましょう。
※2
for_each = statement.value.condition
先ほども説明しましたが、IAM ポリシーを作成するにあたり、condition
は必須ではないです。
そのため、for_each を使用し値が渡されている時のみ設定するようにしております。
※3
policy = data.aws_iam_policy_document.this.json
※1で作成した IAM ポリシードキュメントを json 形式で参照しております。
この他にも、ファイルにポリシーを json 形式で記載しておき、下記の形式で記述することも可能です。
policy = templatefile("ファイルパス", {})
次に IAM ロール関連の記述の説明です。
data "aws_iam_policy_document" "assume_role" { ※1
statement {
principals {
type = var.assume_type
identifiers = var.assume_identifiers
}
effect = "Allow"
actions = ["sts:AssumeRole"]
}
}
resource "aws_iam_role" "this" {
name = local.role_name
description = var.role_description
assume_role_policy = data.aws_iam_policy_document.assume_role.json ※2
managed_policy_arns = concat(var.managed_policy_arns, [aws_iam_policy.this.arn]) ※3
max_session_duration = var.max_session_duration
tags = {
Name = local.role_name
}
}
※1
data "aws_iam_policy_document" "assume_role" {}
IAM ポリシーの時にも登場した data ソースです。
今回は IAM ロールに設定する信頼されたエンティティの定義をしております。
どんな感じで設定されるか最後の方で画像を載せてます。
※2
assume_role_policy = data.aws_iam_policy_document.assume_role.json
※1で定義した data ソースを json 形式で参照しております。
※3
managed_policy_arns = concat(var.managed_policy_arns, [aws_iam_policy.this.arn])
カスタマー管理の IAM ポリシーと、AWS管理の IAM ポリシーを設定する個所です。
list(string)
型で渡す必要があるので、変数 managed_policy_arns と
先ほど作成した IAM ポリシー(aws_iam_policy.this
)の ARN をリストに入れ、
concat
で二つの list を結合しております。
concat について ⇒ concat Function
module 呼び出し元
今回は module 呼び出しのサンプルを1つ作成。
module "sample_iam_1" {
source = "./modules/iam"
prefix = local.prefix
subname = "sample-1"
# IAM Role
role_description = "sample iam role 1"
managed_policy_arns = [
"arn:aws:iam::aws:policy/AmazonEC2FullAccess"
]
assume_type = "Service" ※1
assume_identifiers = ["ec2.amazonaws.com"]
# IAM Policy
policy_description = "sample iam policy 1"
policy_statement = [
{
effect = "Allow"
actions = ["s3:*"] ※2
resources = [module.s3_logs.bucket_arn] ※3
condition = [ ※4
{
test = "NumericLessThanEquals"
variable = "aws:MultiFactorAuthAge"
values = ["3600"]
}
]
# condition を設定しない場合は condition = []
}
]
}
※1
assume_type = "Service"
信頼されたエンティティに設定するプリンシパルのタイプを定義します。
渡すことのできる値は下記のいずれか。
- AWS
- Service
- Federated
- CanonicalUser
- *
type が AWS の場合は assume_identifiers に アカウントIDのリストを渡したりします。
※2
actions = ["s3:*"]
IAM ポリシーで許可するアクションのリスト
サンプルの様に*
を用いることが可能です。
ただ、マネコンと異なりガバガバすぎるポリシーでも警告されないので注意。
※3
resources = [module.s3_logs.bucket_arn]
S3バケットを作成する module の返り値である ARN を指定している。
S3に関する記事は、こちらをクリック
※4
condition = [・・・]
condition については先ほども記述しましたが、
condition = []
とすることで設定しないことも可能です。
AWS リソース
まずは IAM ポリシー
ポリシーが作成されており内容も問題ないので OK
次に IAM ロール
今回作成した IAM ポリシーだけでなく、EC2フルアクセスの AWS 管理ポリシーもついているので OK
さいごに
最後までご覧いただきありがとうございました。
IAM ポリシーの内容が適当なので、ちゃんとしたサンプルを今度追加する予定です。
(EC2 の module を作成したタイミングでサンプル追加しようかなとか思っていたり。)
今後もGitHubは更新していく予定なので役に立ったら記事にコメントでもしてくれると嬉しくて泣きます。
module の変更案などもコメントしてください。
ではでは。