如何将 IAM 角色附加到 EC2 实例,以便它们可以从 Terraform 中的 ECR 中提取特定图像
How to attach IAM roles to EC2 instances so they can pull an specific image from ECR in Terraform
我正在尝试将 IAM 角色附加到 EC2 实例(而非 ECS),以便它们可以从 ECR 中提取图像。
做这样的事情。请注意,您可能希望限制可访问的 ECR 存储库。
resource "aws_instance" "test" {
...
}
resource "aws_launch_configuration" "ecs_cluster" {
...
iam_instance_profile = "${aws_iam_instance_profile.test.id}"
}
resource "aws_iam_role" "test" {
name = "test_role"
assume_role_policy = "..."
}
resource "aws_iam_instance_profile" "test" {
name = "ec2-instance-profile"
role = "${aws_iam_role.test.name}"
}
resource "aws_iam_role_policy_attachment" "test" {
role = "${aws_iam_role.test.name}"
policy_arn = "${aws_iam_policy.test.arn}"
}
resource "aws_iam_policy" "test" {
name = "ec2-instance-pulls-from-ecr"
description = "EC2 instance can pull from ECR"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
],
"Resource": "*"
}
]
}
EOF
}
已知这在 Terraform v0.11.13 中有效
cluster.tf
locals {
cluster_name = "cluster-${terraform.workspace}"
}
resource "aws_iam_role_policy" "cluster_member" {
name = "${local.cluster_name}"
role = "${aws_iam_role.cluster_member.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:UpdateContainerInstancesState",
"ecs:DeregisterContainerInstance",
"ecs:DiscoverPollEndpoint",
"ecs:Poll",
"ecs:RegisterContainerInstance",
"ecs:StartTelemetrySession",
"ecs:Submit*",
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_role" "cluster_member" {
name = "${local.cluster_name}"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_instance_profile" "cluster_member" {
name = "${local.cluster_name}"
role = "${aws_iam_role.cluster_member.name}"
}
data "template_file" "cloud_config" {
template = "${file("${path.module}/templates/user_data.sh")}"
vars {
ecs_cluster = "${local.cluster_name}"
}
}
resource "aws_instance" "cluster_member" {
# http://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html
iam_instance_profile = "${aws_iam_instance_profile.cluster_member.name}"
user_data = "${data.template_file.cloud_config.rendered}"
}
templates/user_data.sh
#!/bin/bash
# See https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_container_instance.html
cat <<'EOF' >> /etc/ecs/ecs.config
ECS_CLUSTER=${ecs_cluster}
EOF
@Eric M. Johnson 给出的答案是正确的,只是为了完整性,
resource "aws_launch_configuration" "ecs_launch_configuration" {
name = "${var.application_name}-${var.stack}"
image_id = var.image_id
instance_type = var.instance_type
iam_instance_profile = aws_iam_instance_profile.esc_launch_configuration_iam_instance_profile.arn
security_groups = split(",",aws_security_group.ecs_launch_configuration_security_group.id)
associate_public_ip_address = "true"
// key_name = "${var.ecs-key-pair-name}"
user_data = data.template_file.user_data.rendered
}
data "template_file" "user_data" {
template = file("${path.module}/ec2/user-data.sh")
vars = {
ecs_cluster_name = "${var.application_name}-${var.stack}"
}
}
resource "aws_iam_instance_profile" "esc_launch_configuration_iam_instance_profile" {
name = "${var.application_name}-${var.stack}"
role = aws_iam_role.iam_role.name
}
resource "aws_iam_role" "iam_role" {
name = "${var.application_name}-${var.stack}"
force_detach_policies = true
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": [
"ec2.amazonaws.com",
"ecs.amazonaws.com"
]
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "iam_role_policy_attachment" {
role = aws_iam_role.iam_role.name
policy_arn = aws_iam_policy.ecs_iam_policy.arn
}
resource "aws_iam_policy" "ecs_iam_policy" {
name = "${var.application_name}-${var.stack}"
description = "EC2 instance can pull from ECR"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeTags",
"ecs:CreateCluster",
"ecs:DeregisterContainerInstance",
"ecs:DiscoverPollEndpoint",
"ecs:Poll",
"ecs:RegisterContainerInstance",
"ecs:StartTelemetrySession",
"ecs:UpdateContainerInstancesState",
"ecs:Submit*",
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
EOF
}
我正在尝试将 IAM 角色附加到 EC2 实例(而非 ECS),以便它们可以从 ECR 中提取图像。
做这样的事情。请注意,您可能希望限制可访问的 ECR 存储库。
resource "aws_instance" "test" {
...
}
resource "aws_launch_configuration" "ecs_cluster" {
...
iam_instance_profile = "${aws_iam_instance_profile.test.id}"
}
resource "aws_iam_role" "test" {
name = "test_role"
assume_role_policy = "..."
}
resource "aws_iam_instance_profile" "test" {
name = "ec2-instance-profile"
role = "${aws_iam_role.test.name}"
}
resource "aws_iam_role_policy_attachment" "test" {
role = "${aws_iam_role.test.name}"
policy_arn = "${aws_iam_policy.test.arn}"
}
resource "aws_iam_policy" "test" {
name = "ec2-instance-pulls-from-ecr"
description = "EC2 instance can pull from ECR"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
],
"Resource": "*"
}
]
}
EOF
}
已知这在 Terraform v0.11.13 中有效
cluster.tf
locals {
cluster_name = "cluster-${terraform.workspace}"
}
resource "aws_iam_role_policy" "cluster_member" {
name = "${local.cluster_name}"
role = "${aws_iam_role.cluster_member.id}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:UpdateContainerInstancesState",
"ecs:DeregisterContainerInstance",
"ecs:DiscoverPollEndpoint",
"ecs:Poll",
"ecs:RegisterContainerInstance",
"ecs:StartTelemetrySession",
"ecs:Submit*",
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_role" "cluster_member" {
name = "${local.cluster_name}"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_instance_profile" "cluster_member" {
name = "${local.cluster_name}"
role = "${aws_iam_role.cluster_member.name}"
}
data "template_file" "cloud_config" {
template = "${file("${path.module}/templates/user_data.sh")}"
vars {
ecs_cluster = "${local.cluster_name}"
}
}
resource "aws_instance" "cluster_member" {
# http://docs.aws.amazon.com/AmazonECS/latest/developerguide/instance_IAM_role.html
iam_instance_profile = "${aws_iam_instance_profile.cluster_member.name}"
user_data = "${data.template_file.cloud_config.rendered}"
}
templates/user_data.sh
#!/bin/bash
# See https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_container_instance.html
cat <<'EOF' >> /etc/ecs/ecs.config
ECS_CLUSTER=${ecs_cluster}
EOF
@Eric M. Johnson 给出的答案是正确的,只是为了完整性,
resource "aws_launch_configuration" "ecs_launch_configuration" {
name = "${var.application_name}-${var.stack}"
image_id = var.image_id
instance_type = var.instance_type
iam_instance_profile = aws_iam_instance_profile.esc_launch_configuration_iam_instance_profile.arn
security_groups = split(",",aws_security_group.ecs_launch_configuration_security_group.id)
associate_public_ip_address = "true"
// key_name = "${var.ecs-key-pair-name}"
user_data = data.template_file.user_data.rendered
}
data "template_file" "user_data" {
template = file("${path.module}/ec2/user-data.sh")
vars = {
ecs_cluster_name = "${var.application_name}-${var.stack}"
}
}
resource "aws_iam_instance_profile" "esc_launch_configuration_iam_instance_profile" {
name = "${var.application_name}-${var.stack}"
role = aws_iam_role.iam_role.name
}
resource "aws_iam_role" "iam_role" {
name = "${var.application_name}-${var.stack}"
force_detach_policies = true
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": [
"ec2.amazonaws.com",
"ecs.amazonaws.com"
]
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "iam_role_policy_attachment" {
role = aws_iam_role.iam_role.name
policy_arn = aws_iam_policy.ecs_iam_policy.arn
}
resource "aws_iam_policy" "ecs_iam_policy" {
name = "${var.application_name}-${var.stack}"
description = "EC2 instance can pull from ECR"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeTags",
"ecs:CreateCluster",
"ecs:DeregisterContainerInstance",
"ecs:DiscoverPollEndpoint",
"ecs:Poll",
"ecs:RegisterContainerInstance",
"ecs:StartTelemetrySession",
"ecs:UpdateContainerInstancesState",
"ecs:Submit*",
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
EOF
}