Работа с AWS IAM и Terraform в Unix/Linux

Работа с AWS IAM и Terraform в Unix/Linux

AWS IAM (Identity and Access Management) — это веб-сервис, который дает возможность контролировать доступ к ресурсам AWS. Вы используете IAM для контроля того, кто аутентифицирован и авторизован (имеет разрешения) для использования ресурсов. Когда вы сначала создаете учетную запись AWS, вы начинаете с единого идентификатора входа, который имеет полный доступ ко всем услугам и ресурсам AWS в рамках учетной записи.  Этот идентификатор называется пользователем учетной записи в AWS, и к нему можно получить доступ, выполнив вход с адресом электронной почты и паролем, который использовался для создания учетной записи.

Рекомендуется не использовать root пользователя для выполнения ваших повседневных задач, даже административных. Он служит только для создания аккаунтов в 1-й раз, а потом не используется (для наилучшей безопастности).

Установка terraform в Unix/Linux

Установка крайне примитивная и я описал как это можно сделать тут:

Установка terraform в Unix/Linux

Так же, в данной статье, я создал скрипт для автоматической установки данного ПО. Он был протестирован на CentOS 6/7, Debian 8 и на Mac OS X. Все работает должным образом!

Работа с AWS IAM и Terraform в Unix/Linux

У меня есть папка terraform, в ней у меня будут лежать провайдеры с которыми я буду работать. Т.к в этом примере я буду использовать AWS, то создам данную папку и перейду в нее. Далее, в этой папке, стоит создать:

$ mkdir examples modules

В папке examples, я буду хранить так званые «плейбуки» для разварачивания различных служб, например — zabbix-server, grafana, web-серверы и так далее. В modules директории, я буду хранить все необходимые модули.

Начнем писать модуль, но для этой задачи, я создам папку:

$  mkir modules/iam

Переходим в нее:

$ cd modules/iam

Открываем файл:

$ vim iam.tf

В данный файл, вставляем:

#---------------------------------------------------
# Instance Profile
#---------------------------------------------------
resource "aws_iam_instance_profile" "profile" {
    name = "${var.name}-profile-${var.environment}-${var.region}"
    role = "${aws_iam_role.role.name}"
}
#----------------------------------------------------
# IAM Role
#----------------------------------------------------
resource "aws_iam_role" "role" {
  name        = "${var.name}-role-${var.environment}-${var.region}"
  description = "IMA ${var.name}-role-${var.environment}-${var.region} role"
  path        = "/"
  assume_role_policy ="${data.aws_iam_policy_document.role-policy-document.json}"
}
data "aws_iam_policy_document" "role-policy-document" {
  "statement" {
    effect = "Allow"

    principals {
      identifiers = [
        "${var.aws_iam_role-principals}",
      ]

      type = "Service"
    }

    actions = [
      "sts:AssumeRole",
    ]
  }
}
#----------------------------------------------------
# IAM Policy
#----------------------------------------------------
resource "aws_iam_policy" "policy" {
  name        = "${var.name}-policy-${var.environment}-${var.region}"
  description = "AIM ${var.name}-policy-${var.environment}-${var.region} policy"
  policy      = "${data.aws_iam_policy_document.policy-document.json}"
}
data "aws_iam_policy_document" "policy-document" {
  "statement" {
    effect = "Allow"

    resources = [
      "${var.aws_iam_policy-resources}",
    ]

    actions = [
      "${var.aws_iam_policy-actions}",
    ]
  }
}
#----------------------------------------------------
# IAM Policy Attachment
#----------------------------------------------------
resource "aws_iam_policy_attachment" "iam_policy_attachment" {
  name        = "${var.name}-iam_policy_attachment-${var.environment}-${var.region}"
  roles       = ["${aws_iam_role.role.name}"]
  policy_arn  = "${aws_iam_policy.policy.arn}"
}

Что тут описано…. Я поделил данный файл на 4 части:

  • Instance Profile — Прописываем пропиль инстанса.
  • IAM Role — Создаем IAM роль.
  • IAM Policy — Задаем полиси для созданной IAM роли.
  • IAM Policy Attachment — Прикрепляем созданную роль, полиси к инстансу.

Открываем файл:

$ vim variables.tf

И прописываем:

#-----------------------------------------------------------
# Global or/and default variables
#-----------------------------------------------------------
variable "name" {
  description = "Name to be used on all resources as prefix"
  default     = "TEST-AIM"
}

variable "region" {
  description = "The region where to deploy this code (e.g. us-east-1)."
  default     = "us-east-1"
}
#---------------------------------------------------------------
# Custom variables
#---------------------------------------------------------------
variable "environment" {
    description = "environment for service"
    default     = "PROD"
}
variable "aws_iam_role-principals" {
  type        = "list"
  description = "List of allowed actions."
}
variable "aws_iam_policy-resources" {
  type        = "list"
  description = "List of allowed actions."
  default     = ["*"]
}
variable "aws_iam_policy-actions" {
  type        = "list"
  description = "List of allowed actions."
  # default     = ["*"]

}

Собственно в этом файле храняться все переменные. Спасибо кэп!

Открываем последний файл:

$ vim outputs.tf

и в него вставить нужно следующие строки:

output "instance_profile_uid" {
    value = "${aws_iam_instance_profile.profile.unique_id}"
}
output "role_arn" {
    value = "${aws_iam_role.role.arn}"
}

output "role_name" {
    value = "${aws_iam_role.role.name}"
}

output "policy_name" {
    value = "${aws_iam_policy.policy.name}"
}
output "AWS region" {
    value = "${var.region}"
}

output "role_id" {
  value = "${aws_iam_role.role.id}"
}

Данный файл служит для того, чтобы выводить нужные значения на экран вашего экрана.

Переходим теперь в папку aws/examples и создадим еще одну папку для проверки написанного чуда:

$ mkdir aim && cd $_

Внутри созданной папки открываем файл:

$ vim main.tf

И вставим в него следующий код:

#
# MAINTAINER Vitaliy Natarov "vitaliy.natarov@yahoo.com"
#
terraform {
  required_version = "> 0.9.0"
}
provider "aws" {
    region  = "us-east-1"
    # access_key = "${var.aws_access_key}"
    # secret_key = "${var.aws_secret_key}"
    #
}

module "aim" {
    source                          = "../../modules/iam"
    name                            = "TEST-AIM"
    region                          = "us-east-1"
    environment                     = "PROD"

    aws_iam_role-principals         = [
        "ec2.amazonaws.com",
    ]
    aws_iam_policy-actions           = [
        "cloudwatch:GetMetricStatistics",
        "logs:DescribeLogStreams",
        "logs:GetLogEvents",
        "elasticache:Describe*",
        "rds:Describe*",
        "rds:ListTagsForResource",
        "ec2:DescribeAccountAttributes",
        "ec2:DescribeAvailabilityZones",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeVpcs",
  ]
}

Все уже написано и готово к использованию. Ну что, начнем тестирование. В папке с вашим плейбуком, выполняем:

$ terraform init

Этим действием я инициализирую проект. Затем, подтягиваю модуль:

$ terraform get

PS: Для обновление изменений в самом модуле, можно выполнять:

$ terraform get -update

Запускем прогон:

$ terraform plan

Вывод будет такой:

Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.

data.aws_iam_policy_document.role-policy-document: Refreshing state...
data.aws_iam_policy_document.policy-document: Refreshing state...

------------------------------------------------------------------------

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + module.aim.aws_iam_instance_profile.profile
      id:                    <computed>
      arn:                   <computed>
      create_date:           <computed>
      name:                  "TEST-AIM-profile-PROD-us-east-1"
      path:                  "/"
      role:                  "TEST-AIM-role-PROD-us-east-1"
      roles.#:               <computed>
      unique_id:             <computed>

  + module.aim.aws_iam_policy.policy
      id:                    <computed>
      arn:                   <computed>
      description:           "AIM TEST-AIM-policy-PROD-us-east-1 policy"
      name:                  "TEST-AIM-policy-PROD-us-east-1"
      path:                  "/"
      policy:                "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"rds:ListTagsForResource\",\n        \"rds:Describe*\",\n        \"logs:GetLogEvents\",\n        \"logs:DescribeLogStreams\",\n        \"elasticache:Describe*\",\n        \"ec2:DescribeVpcs\",\n        \"ec2:DescribeSecurityGroups\",\n        \"ec2:DescribeAvailabilityZones\",\n        \"ec2:DescribeAccountAttributes\",\n        \"cloudwatch:GetMetricStatistics\"\n      ],\n      \"Resource\": \"*\"\n    }\n  ]\n}"

  + module.aim.aws_iam_policy_attachment.iam_policy_attachment
      id:                    <computed>
      name:                  "TEST-AIM-iam_policy_attachment-PROD-us-east-1"
      policy_arn:            "${aws_iam_policy.policy.arn}"
      roles.#:               "1"
      roles.2598150538:      "TEST-AIM-role-PROD-us-east-1"

  + module.aim.aws_iam_role.role
      id:                    <computed>
      arn:                   <computed>
      assume_role_policy:    "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": \"sts:AssumeRole\",\n      \"Principal\": {\n        \"Service\": \"ec2.amazonaws.com\"\n      }\n    }\n  ]\n}"
      create_date:           <computed>
      description:           "IMA TEST-AIM-role-PROD-us-east-1 role"
      force_detach_policies: "false"
      name:                  "TEST-AIM-role-PROD-us-east-1"
      path:                  "/"
      unique_id:             <computed>


Plan: 4 to add, 0 to change, 0 to destroy.

------------------------------------------------------------------------

Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Мне вывело что все у меня хорошо и можно запускать деплой:

$ terraform apply

Вывод будет:

data.aws_iam_policy_document.role-policy-document: Refreshing state...
data.aws_iam_policy_document.policy-document: Refreshing state...

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + module.aim.aws_iam_instance_profile.profile
      id:                    <computed>
      arn:                   <computed>
      create_date:           <computed>
      name:                  "TEST-AIM-profile-PROD-us-east-1"
      path:                  "/"
      role:                  "TEST-AIM-role-PROD-us-east-1"
      roles.#:               <computed>
      unique_id:             <computed>

  + module.aim.aws_iam_policy.policy
      id:                    <computed>
      arn:                   <computed>
      description:           "AIM TEST-AIM-policy-PROD-us-east-1 policy"
      name:                  "TEST-AIM-policy-PROD-us-east-1"
      path:                  "/"
      policy:                "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"rds:ListTagsForResource\",\n        \"rds:Describe*\",\n        \"logs:GetLogEvents\",\n        \"logs:DescribeLogStreams\",\n        \"elasticache:Describe*\",\n        \"ec2:DescribeVpcs\",\n        \"ec2:DescribeSecurityGroups\",\n        \"ec2:DescribeAvailabilityZones\",\n        \"ec2:DescribeAccountAttributes\",\n        \"cloudwatch:GetMetricStatistics\"\n      ],\n      \"Resource\": \"*\"\n    }\n  ]\n}"

  + module.aim.aws_iam_policy_attachment.iam_policy_attachment
      id:                    <computed>
      name:                  "TEST-AIM-iam_policy_attachment-PROD-us-east-1"
      policy_arn:            "${aws_iam_policy.policy.arn}"
      roles.#:               "1"
      roles.2598150538:      "TEST-AIM-role-PROD-us-east-1"

  + module.aim.aws_iam_role.role
      id:                    <computed>
      arn:                   <computed>
      assume_role_policy:    "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": \"sts:AssumeRole\",\n      \"Principal\": {\n        \"Service\": \"ec2.amazonaws.com\"\n      }\n    }\n  ]\n}"
      create_date:           <computed>
      description:           "IMA TEST-AIM-role-PROD-us-east-1 role"
      force_detach_policies: "false"
      name:                  "TEST-AIM-role-PROD-us-east-1"
      path:                  "/"
      unique_id:             <computed>


Plan: 4 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

module.aim.aws_iam_policy.policy: Creating...
  arn:         "" => "<computed>"
  description: "" => "AIM TEST-AIM-policy-PROD-us-east-1 policy"
  name:        "" => "TEST-AIM-policy-PROD-us-east-1"
  path:        "" => "/"
  policy:      "" => "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"rds:ListTagsForResource\",\n        \"rds:Describe*\",\n        \"logs:GetLogEvents\",\n        \"logs:DescribeLogStreams\",\n        \"elasticache:Describe*\",\n        \"ec2:DescribeVpcs\",\n        \"ec2:DescribeSecurityGroups\",\n        \"ec2:DescribeAvailabilityZones\",\n        \"ec2:DescribeAccountAttributes\",\n        \"cloudwatch:GetMetricStatistics\"\n      ],\n      \"Resource\": \"*\"\n    }\n  ]\n}"
module.aim.aws_iam_role.role: Creating...
  arn:                   "" => "<computed>"
  assume_role_policy:    "" => "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Sid\": \"\",\n      \"Effect\": \"Allow\",\n      \"Action\": \"sts:AssumeRole\",\n      \"Principal\": {\n        \"Service\": \"ec2.amazonaws.com\"\n      }\n    }\n  ]\n}"
  create_date:           "" => "<computed>"
  description:           "" => "IMA TEST-AIM-role-PROD-us-east-1 role"
  force_detach_policies: "" => "false"
  name:                  "" => "TEST-AIM-role-PROD-us-east-1"
  path:                  "" => "/"
  unique_id:             "" => "<computed>"
module.aim.aws_iam_policy.policy: Creation complete after 1s (ID: arn:aws:iam::316963130188:policy/TEST-AIM-policy-PROD-us-east-1)
module.aim.aws_iam_role.role: Creation complete after 1s (ID: TEST-AIM-role-PROD-us-east-1)
module.aim.aws_iam_instance_profile.profile: Creating...
  arn:         "" => "<computed>"
  create_date: "" => "<computed>"
  name:        "" => "TEST-AIM-profile-PROD-us-east-1"
  path:        "" => "/"
  role:        "" => "TEST-AIM-role-PROD-us-east-1"
  roles.#:     "" => "<computed>"
  unique_id:   "" => "<computed>"
module.aim.aws_iam_policy_attachment.iam_policy_attachment: Creating...
  name:             "" => "TEST-AIM-iam_policy_attachment-PROD-us-east-1"
  policy_arn:       "" => "arn:aws:iam::316963130188:policy/TEST-AIM-policy-PROD-us-east-1"
  roles.#:          "" => "1"
  roles.2598150538: "" => "TEST-AIM-role-PROD-us-east-1"
module.aim.aws_iam_instance_profile.profile: Creation complete after 2s (ID: TEST-AIM-profile-PROD-us-east-1)
module.aim.aws_iam_policy_attachment.iam_policy_attachment: Creation complete after 3s (ID: TEST-AIM-iam_policy_attachment-PROD-us-east-1)

Apply complete! Resources: 4 added, 0 changed, 0 destroyed.

Как видно с вывода, — все прошло гладко! Чтобы удалить созданное творение, можно выполнить:

$ terraform destroy

Вот и все на этом. Данная статья «Работа с AWS IAM и Terraform в Unix/Linux» завершена.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *