RobotsAndPencils / terraform-ecs-autoscaling

A terraform module for creating an AWS autoscaling group for ECS
MIT License
67 stars 15 forks source link

Ensure IAM profile exists and is correctly configured. #2

Open rclayton-the-terrible opened 9 years ago

rclayton-the-terrible commented 9 years ago

First of all, thank you. This TF config greatly inspired some work I've been doing bootstrapping and ECS cluster.

During my exploration of the process, I've ran into a couple of IAM related issues. I don't think Amazon explains this well enough, and after working with multiple Amazon accounts, I'm baffled at how I got AWS to auto configure itself the first time (subsequent attempts didn't work). Through this experience, I've documented the issues and added Terraform resources to ensure I can consistently provision ECS clusters.

# IAM Role for ECS Instances in EC2
resource "aws_iam_role" "ecs_instance_role" {
  name = "ecsInstanceRole"
  assume_role_policy = "${file("files/ecs_instance_role_trust.json")}"
}

# Attach the pre-baked AWS policy "AmazonEC2ContainerServiceRole" to the ecsInstanceRole.
# This role allows ECS Instances to modify load balancers to register Docker containers as instances.
resource "aws_iam_policy_attachment" "ecs_service_role" {
  name = "ecs_service_role"
  roles = ["${aws_iam_role.ecs_instance_role.name}"]
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceRole"
}

# Attach the pre-baked AWS policy "AmazonEC2ContainerServiceforEC2Role" to the ecsInstanceRole.
# This role allows ECS Instances to connect to the ECS Management infrastructure of EC2.
resource "aws_iam_policy_attachment" "ecs_service_ec2_role" {
  name = "ecs_service_ec2_role"
  roles = ["${aws_iam_role.ecs_instance_role.name}"]
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceforEC2Role"
}

# Create an instance profile for this ecsInstanceRole.  This is assigned to the machine
# to allow it to assume the ecsInstanceRole (basically like an anonymous account that can be
# assumed by EC2 resources).
resource "aws_iam_instance_profile" "ecs_instance_profile" {
  name = "ecsInstanceRole"
  roles = ["${aws_iam_role.ecs_instance_role.name}"]
}

And the referenced Trust relationship:

{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    },
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
revett commented 9 years ago

+1 thanks @rclayton-the-terrible

kurron commented 8 years ago

This helped me as well. Creating the equivalent roles and policies with Terraform just didn't work for me so I followed your lead and reused the baked in ones.

kurron commented 8 years ago

I was able to eliminate the need to use the Amazon profiles (it requires that somebody go through the wizard at least once). The Amazon documentation provided me with the necessary policies:

resource "aws_iam_instance_profile" "ecs_profile" {
    name = "ecs-instance-profile"
    roles = ["${aws_iam_role.ecs_instance_role.name}"]
}

# the trick is to provide TWO trust policies -- one for each role
resource "aws_iam_role" "ecs_instance_role" {
    name = "ecs-instance-role"
#   path = "/"
    assume_role_policy = <<EOF
{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    },
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "ecs_instance_role" {
    name = "ecs-instance-role"
    role = "${aws_iam_role.ecs_instance_role.id}"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecs:CreateCluster",
        "ecs:DeregisterContainerInstance",
        "ecs:DiscoverPollEndpoint",
        "ecs:Poll",
        "ecs:RegisterContainerInstance",
        "ecs:StartTelemetrySession",
        "ecs:Submit*"
      ],
      "Resource": "*"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy" "ecs_scheduler_role" {
    name = "ecs-scheduler-role"
    role = "${aws_iam_role.ecs_instance_role.id}"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:AuthorizeSecurityGroupIngress",
        "ec2:Describe*",
        "elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
        "elasticloadbalancing:Describe*",
        "elasticloadbalancing:RegisterInstancesWithLoadBalancer"
      ],
      "Resource": "*"
    }
  ]
}
EOF
}
fii commented 8 years ago

Thank you !

nathanpeck commented 7 years ago

For further reference here is a link to the AWS documentation about this instance role that is necessary for an EC2 instance to communicate with the ECS service on your behalf: http://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html

mikejw commented 6 years ago

This info really helped me!