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

AWS IAMについての忘備録

目的

  • AWSソリューションアーキテクトの勉強を踏まえてUdemyで勉強中
  • ただコンソールを触っていてもつまらないのでTerraformの勉強を含めてハンズオンを実施

投稿で説明すること

  • IAMについての基本的な説明
    • IAMとは
    • IAMユーザ
    • IAMグループ
    • IAMロール
    • IAMポリシー
  • Terraformを使ったハンズオン
    • ポリシーの作成
    • グループの作成
      • ポリシーをアタッチ
    • ユーザの作成
      • グループに参加させる

IAMの概要

  • AWS Identity and Access Managementの略をとってIAM
  • AWS利用者認証の設定やアクセスポリシーの設定、ユーザまたはグループに対してアクセス制限を与えたりする

全体のイメージ

  • IAMユーザにポリシーを適用する場合には1ユーザに紐づいている
  • IAMグループは複数のIAMユーザが所属している
  • IAMロールはあるAWSサービスが別のAWSサービスに操作を行う場合
    • EC2がS3に対してファイルをアップロードするなど

無題のプレゼンテーション (2).jpg

IAMユーザ

  • ルートユーザとルートユーザから作成されるユーザが存在する
    • ルートユーザはAWSアカウントを作成した際に一番最初に作られる
    • Admin権限以外にAWSサービスの停止やルートユーザのアカウントなどルートユーザにしかできない操作がある
    • アクセスキーが漏洩した場合には影響が非常に大きいため、通常の開発や運用では利用しない
    • MFA(多要素認証)を設定しておき、乗っ取られない対策をしておく
  • 1つのAWSアカウントに対して5000ユーザまで作成が可能
  • 個人利用であればIAMユーザを作成してそれぞれにIAMポリシーを割り当てればいいかもしれない、各人毎にポリシーをアタッチするのは面倒が多すぎる

IAMグループ

  • 複数のIAMユーザを特定のグループに束ねる
    • AさんとBさんはシステム管理者なのでAdministratorグループに所属
    • Cさんはシステム運用者なのでOperationグループに所属
  • 1つのAWSアカウントで300グループまで作成が可能

無題のプレゼンテーション (3).jpg

IAMポリシー

  • どのリソースにアクセスできるのかJSON形式で定義したもの
    • ACLに近いかもしれない
  • Effect
    • Allow:リソースへの操作を許可する
    • Deny:リソースへの操作を拒否する
  • Action
    • ポリシーをかける対象の操作
      • S3に保存されているオブジェクトの取得など
  • Resource
    • ある特定のAWSリソースに限定する場合にARNで記述する
  • Condition
    • ポリシーが適用される条件
      • 特定のIPアドレスからの接続のみ許可など
S3へのフルアクセスを許可する場合
{
    "Effect": "Allow",
    "Action": [
        "S3:*",
    ],
    "Resources": [
        "arn:aws:s3::mybucket"
    ],
    "Condition": {
        "IpAddress":{
            "aws:SourceIP":
            ["192.168.10.1/32"]
        }
    }
}
  • ポリシーには管理ポリシーインラインポリシーが存在する

管理ポリシー

  • 1つのポリシーを複数のユーザやグループに同種の権限を付与できる
  • AWS管理ポリシーとカスタマー管理ポリシーが存在する
    • AWS管理ポリシーはAWS側が用意しているポリシー
    • カスタマー管理ポリシーはユーザ自身が管理するポリシー
      • 最大5世代までバージョン管理が可能 ### インラインポリシー
  • ポリシーと対象が1対1で紐づくポリシー
    • 複数のユーザ・グループで同種のポリシーを共有できない

Terraformでのハンズオン

前提

  • Terraformを扱えるAdministratorAccessポリシーをアタッチしたIAMユーザを作成している
  • Terraformの環境構築が完了している ## 想定
  • AdministratorPolicyの操作権限もつIAMグループを作成する(グループ名Administrator)
  • AmazonEC2FullAccessAmazonS3FullAccessの操作権限をもつIAMグループを作成する(グループ名Application)
  • AmazonEC2FullAccessAmazonS3FullAccessAWSConfigRoleも操作権限をもつIAMグループを作成する ## ディレクトリ構造
.
├── iam_policy
│   ├── main.tf
│   └── policy
│       ├── administrator_policy.json
│       ├── application_policy.json
│       └── operation_policy.json
├── main.tf
└── note.md

IAMグループを作成(/iam_policy)

  • AWS管理ポリシーをそのまま利用しているため、ポリシーのJSONについては今回は割愛
  • resource aws_iam_policyでIAMポリシーを作成する
  • policy = "${file("ファイルパス")}で適用するポリシーを定義する
    • もちろんtfファイルにインラインで書くこともできる
  • 後でIAM GroupにアタッチするのでoutputでARNを出力させています
iam_policy/main.tf
resource "aws_iam_policy" "AdministrationPolicy" {
    name   = "AdministerPolicy"
    policy = "${file("iam_policy/policy/administrator_policy.json")}"
}

resource "aws_iam_policy" "ApplicationPolicy" {
    name   = "AppcalitionPolicy"
    policy = "${file("iam_policy/policy/application_policy.json")}"
}

resource "aws_iam_policy" "OperationPolicy" {
    name   = "OpperationPolicy"
    policy = "${file("iam_policy/policy/operation_policy.json")}"
}

#
# Ouput
#
output "Administrator_policy_arn" {
    value = "${aws_iam_policy.AdministrationPolicy.arn}"
}
output "Application_policy_arn" {
    value = "${aws_iam_policy.ApplicationPolicy.arn}"
}
output "Operation_policy_arn" {
    value = "${aws_iam_policy.OperationPolicy.arn}"
}

IAMユーザを作成

  • aws_iam_userでIAMユーザを作成する
    • force_destoryを設定するとIAMユーザを削除時にログインプロファイルやアクセスキーも一緒に削除してくれる
  • aws_iam_user_login_profileはWebコンソールログイン時のログイン情報となる

    • pgp_keyの設定にはbase64でエンコードされた公開鍵かkeybaseで作成したユーザと紐付ける
    • 今回はgpgコマンドで作成し、base64文字列を変数に入れて実装
    • テストだから1個しか作らなかったが、本番利用時にはユーザ毎に証明書を作成する
  • aws_iam_access_keyはAWS-CLIやAPIを利用する際に使う認証情報となる

iam_user/main.tf
variable "pgp_key" {
    default = "(base64でエンコードされた公開鍵)"
}
#
# Adminユーザ
#
resource "aws_iam_user" "admin_exp" {
    name          = "admin.example.one"
    path          = "/"
    force_destroy = true
}

resource "aws_iam_user_login_profile" "admin_exp_login_profile" {
    user    = "${aws_iam_user.admin_exp.name}"
    pgp_key = "${var.pgp_key}"
}

resource "aws_iam_access_key" "admin_exp_access_key" {
    user    = "${aws_iam_user.admin_exp.name}"
    pgp_key = "${var.pgp_key}"
}

output "administrator_IAM_name" {
    value = "${aws_iam_access_key.admin_exp_access_key.*.user}"
}

output "administrator_IAM_id" {
    value = "${aws_iam_access_key.admin_exp_access_key.*.id}"
}

output "administrator_IAM_encrypted_secret" {
    value = "${aws_iam_access_key.admin_exp_access_key.*.encrypted_secret}"
}


#
# Operationユーザ
#
resource "aws_iam_user" "operation_exp" {
    name          = "operaion.example.one"
    path          = "/user/operation"
    force_destroy = true
}

resource "aws_iam_user_login_profile" "operation_exp_login_profile" {
    user    = "${aws_iam_user.operation_exp.name}"
    pgp_key = "${var.pgp_key}"
}

resource "aws_iam_access_key" "operation_exp_acccess_key" {
    user    = "${aws_iam_user.operation_exp.name}"
    pgp_key = "${var.pgp_key}"
}

output "operations_IAM_name" {
    value = "${aws_iam_access_key.operation_exp_acccess_key.*.user}"
}

output "operations_IAM_id" {
    value = "${aws_iam_access_key.operation_exp_acccess_key.*.id}"
}

output "operations_IAM_encrypted_secret" {
    value = "${aws_iam_access_key.operation_exp_acccess_key.*.encrypted_secret}"
}

#
# Application ユーザ
#
resource "aws_iam_user" "application_exp" {
    name          = "operaion.example.one"
    path          = "/user/application"
    force_destroy = true
}

resource "aws_iam_user_login_profile" "application_exp_login_profile" {
    user    = "${aws_iam_user.application_exp.name}"
    pgp_key = "${var.pgp_key}"
}

resource "aws_iam_access_key" "application_exp_access_key" {
    user    = "${aws_iam_user.application_exp.name}"
    pgp_key = "${var.pgp_key}"
}

output "applications_IAM_name" {
    value = "${aws_iam_access_key.application_exp_access_key.*.user}"
}
output "application_IAM_id" {
    value = "${aws_iam_access_key.operation_exp_acccess_key.*.id}"
}
output "application_IAM_encrypted_password" {
    value = "${aws_iam_access_key.operation_exp_acccess_key.*.encrypted_secret}"
}

IAMグループを作成

  • variableは他のモジュールで作成したOutputを受け取る想定
  • aws_iam_groupでIAMグループを作成する
  • aws_iam_group_policy_attachmentでポリシーをアタッチする
  • aws_iam_group_policy_attachmentが肝
    • usersは配列を想定している
    • elementを利用する
/iam_group/main.tf
variable "AdministrationsRoleARN" {}
variable "OperationsRoleARN" {}
variable "ApplicationsRoleARN" {}
variable "AdministrationsUsers" {
    type = "list"
}
variable "OperationsUsers" {
    type = "list"
}
variable "ApplicationsUsers" {
    type = "list"
}


#
# グループ作成
resource "aws_iam_group" "Administrators" {
    name = "Administrators"
    path = "/"
}

resource "aws_iam_group" "Applications" {
    name = "Applications"
    path = "/users/applications/"
}

resource "aws_iam_group" "Operations" {
    name = "Operations"
    path = "/users/operations/"
}

#
# グループへのポリシーアタッチ
#
resource "aws_iam_group_policy_attachment" "AdministratorsPolicyAttachment" {
    group      = "${aws_iam_group.Administrators.name}"
    policy_arn = "${var.AdministrationsRoleARN}"
}
resource "aws_iam_group_policy_attachment" "ApplicationsPolicyAttachment" {
    group      = "${aws_iam_group.Applications.name}"
    policy_arn = "${var.OperationsRoleARN}"
}
resource "aws_iam_group_policy_attachment" "OperationsPolicyAttachment"{
    group      = "${aws_iam_group.Operations.name}"
    policy_arn = "${var.OperationsRoleARN}"
}


#
# ユーザをグループに参加させる
#
resource "aws_iam_group_membership" "Administrations" {
    count = "${length(var.AdministrationsUsers)}"
    name  = "Administrators-group-membership"
    users = [
        "${element(var.AdministrationsUsers, count.index)}"
    ]

    group = "${aws_iam_group.Administrators.name}"
}

resource "aws_iam_group_membership" "Operations" {
    count = "${length(var.OperationsUsers)}"
    name  = "Operations-group-membership"
    users = [
        "${element(var.OperationsUsers, count.index)}"
    ]

    group = "${aws_iam_group.Operations.name}"
}

resource "aws_iam_group_membership" "Applications" {
    count = "${length(var.ApplicationsUsers)}"
    name  = "Applications-group-membership"
    users = [
        "${element(var.ApplicationsUsers, count.index)}"
    ]

    group = "${aws_iam_group.Applications.name}"
}

main.tf

provider "aws" {
  region = "ap-northeast-1"
}


module "iam_policy" {
    source = "./iam_policy"
}

module "iam_user" {
    source = "./iam_user"
}

module "iam_group" {
    # Policy Arn
    AdministrationsRoleARN = "${module.iam_policy.Administrator_policy_arn}"
    OperationsRoleARN      = "${module.iam_policy.Operation_policy_arn}"
    ApplicationsRoleARN    = "${module.iam_policy.Application_policy_arn}"
    # Users
    AdministrationsUsers   = "${module.iam_user.administrator_IAM_name}"
    OperationsUsers        = "${module.iam_user.operations_IAM_name}"
    ApplicationsUsers      = "${module.iam_user.applications_IAM_name}"
    source = "./iam_group"
}

参考

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
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