Help us understand the problem. What is going on with this article?

TerraformでIAMグループ・ユーザを作成する

More than 1 year has passed since last update.
  • 今日は以前から社内からAWSの機能検証を気軽に実施できる環境がほしいというリクエストがあったため、新たにAWSアカウントを作成し、異なる権限をもったIAMグループを作成し、エンジニアごとに所属させたことを記事にしたいと思います。

作成するグループとそれに付与する管理ポリシー

  • グループ名:administrator
    • 管理ポリシー名:AdministratorAccess
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "*",
            "Resource": "*"
        }
    ]
}
  • グループ名:development
    • 管理ポリシー名:PowerUserAccess
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "NotAction": [
                "iam:*",
                "organizations:*"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:CreateServiceLinkedRole",
                "iam:DeleteServiceLinkedRole",
                "iam:ListRoles",
                "organizations:DescribeOrganization"
            ],
            "Resource": "*"
        }
    ]
}
  • グループ名:operators
    • 管理ポリシー名:未設定

作成するユーザ

  • 11ユーザ作成
    • administratorグループへ追加

設定ファイル構成

.
├── README.md
├── iam_group_membership.tf
├── iam_user.tf
├── main.tf
├── terraform_remote_state.tf
└── variables.tf
  • variables.tf
variable "aws_iam_user" {
  type = "list"

  default = [
    "exp.example.yell",
    "exp.example.ange",
    "exp.example.etoile",
    "exp.example.amor",
    "exp.example.macherie",
    "exp.example.whip",
    "exp.example.custerd",
    "exp.example.gelato",
    "exp.example.macaron",
    "exp.example.chocolat",
    "exp.example.parfait",

  ]
}

variable "aws_iam_group" {
  type = "list"

  default = [
    "administrator",
    "development",
    "operators",
  ]
}
  • iam_user.tf
    • シークレットキーはkeybaseを使用して暗号化し、ユーザIDと関連付けしてoutputさせています
resource "aws_iam_user" "example_exp" {
  count         = "${length(var.aws_iam_user)}"
  name          = "${element(var.aws_iam_user, count.index)}"
  path          = "/"
  force_destroy = true
}

resource "aws_iam_user_login_profile" "example_exp_login_profile" {
  count                   = "${length(var.aws_iam_user)}"
  user                    = "${element(var.aws_iam_user, count.index)}"
  pgp_key                 = "keybase:exp_example"
  password_reset_required = true
  password_length         = "20"
}

resource "aws_iam_access_key" "example_exp_access_key" {
  count   = "${length(var.aws_iam_user)}"
  user    = "${element(var.aws_iam_user, count.index)}"
  pgp_key = "keybase:exp_example"
}

output "encrypted_secret" {
  value = "${join("\n", aws_iam_access_key.example_exp_access_key.*.encrypted_secret)}"
}

output "id" {
  value = "${join("\n", aws_iam_access_key.example_exp_access_key.*.id)}"
}

output "user" {
  value = "${join("\n", aws_iam_access_key.example_exp_access_key.*.user)}"
}
  • iam_group_membership.tf
resource "aws_iam_group_membership" "example_exp_group_membership" {
  count = "${length(var.aws_iam_user)}"
  name  = "example_exp_group_membership"

  users = [
    "${element(var.aws_iam_user, count.index)}",
  ]

  group = "${element(var.aws_iam_group, 0)}"
}

resource "aws_iam_group" "example_exp_group" {
  count = "${length(var.aws_iam_group)}"
  name  = "${element(var.aws_iam_group, count.index)}"
}

resource "aws_iam_group_policy_attachment" "policy-attach" {
  group      = "${element(var.aws_iam_group, count.index)}"
  policy_arn = "arn:aws:iam::************:policy/administratoraccess"
}
  • output
$ terraform output
encrypted_secret = wcFMA615XJelCVO0ARAA(snip)
wcFMA615XJelCVO0ARAA(snip)
wcFMA615XJelCVO0ARAA(snip)
wcFMA615XJelCVO0ARAA(snip)
wcFMA615XJelCVO0ARAA(snip)
wcFMA615XJelCVO0ARAA(snip)
wcFMA615XJelCVO0ARAA(snip)
wcFMA615XJelCVO0ARAA(snip)
wcFMA615XJelCVO0ARAA(snip)
wcFMA615XJelCVO0ARAA(snip)
wcFMA615XJelCVO0ARAA(snip)
id = AKIA****************
AKIA****************
AKIA****************
AKIA****************
AKIA****************
AKIA****************
AKIA****************
AKIA****************
AKIA****************
AKIA****************
AKIA****************
AKIA****************
user =exp.example.yell
exp.example.ange
exp.example.etoile
exp.example.amor
exp.example.macherie
exp.example.whip
exp.example.custerd
exp.example.gelato
exp.example.macaron
exp.example.chocolat
exp.example.parfait
  • 作成したユーザ分のシークレットキーをoutputすることはできるんですが、outputにcount処理が使えなく、どのキーがどのユーザに紐付いてるのかわからず...、また、ユーザ分のシークレットキーを復号化する際は、terraform output encrypted_secret | base64 --decode | keybase pgp decryptで処理するんですが、複数のoutputをうまく処理できなく困ってました... どう処理をぶん回すのが効率がいいか悩んでいたところ弊社が誇るRuby関西のFounderでもあるRubyistのcuzic (a.k.a Tomoya Kawanishi )が助けてくれました。「ちょっとまっとき〜」と言って1時間後に下記ワンライナー付きでメンションがきました。
$ terraform output -json | ruby -rjson -ryaml -e 'json = JSON.load(ARGF); keys = %w(user id encrypted_secret); puts [keys, *keys.map{|key| v = json[key]["value"].split; key == "encrypted_secret" ? v.map{|s| `echo #{s} | base64 -d | keybase pgp decrypt -S exp_example`.chomp} : v}.transpose].map{|a| a.join(",")}'

素敵やん...!

  • 実行結果
user,id,encrypted_secret
exp.example.yell,AKIA****************,Ya3R************************************
example.ange,AKIA****************,GYW7************************************
example.etoile,AKIA****************,bUpd************************************
exp.example.amor,AKIA****************,5lHm************************************
exp.example.macherie,AKIA****************,RyoM************************************
exp.example.whip,AKIA****************,r7EW************************************
exp.example.custerd,AKIA****************,CoBk************************************
exp.example.gelato,AKIA****************,FWYd************************************
exp.example.macaron,AKIA****************,4taL************************************
exp.example.chocolat,AKIA****************,4taL************************************
exp.example.parfait,AKIA****************,4taL************************************

最高やん...!

  • これらをまとめてMFAを使うように手順も併せて配布すれば、きっと開発速度が向上し、技術的負債を熨斗付きで返済するようなイノベーションが発生するはず...!
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした