5

Following on the back of this answer, I'm trying to create an aws_iam_role that allows for access to ECR. However, when I define the following:

resource "aws_iam_role" "jenkins_ecr_role" {
  name = "JenkinsECRRole"

  assume_role_policy = <<END_OF_POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ecr.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
END_OF_POLICY
}

I get the error:

Error: Error creating IAM Role JenkinsECRRole:
MalformedPolicyDocument: Invalid principal in policy: "SERVICE":"*"

It looks like ecr.amazonaws.com is a valid principal according to the AWS documentation. What am I doing wrong?

djsumdog
  • 2,560
  • 1
  • 29
  • 55
  • That is allowing ECR to assume the role, not allowing a user/instance profile to assume a role to be able to interact with ECR. – ydaetskcoR Sep 03 '19 at 21:38
  • 1
    @ydaetskcoR So what would be the correct Principal in this situation? – djsumdog Sep 03 '19 at 22:11
  • I made the same assumption. Turns out the `Principal` is what AWS service needs to access ECR. In my case it was some machines in `ecs` that needed the `ecr` permissions. So the `Principal` was `"Service": ["ecs.amazonaws.com"]` – rustyMagnet Feb 24 '22 at 06:47

4 Answers4

1

It seems that this question has not been fully answered so I'll try to give an example on how I added ecr for my gitlab-runner ec2 instance. First off the ec2 instance needs a iam_instance_profile which it seems that you already have. Second: You need the assume-role so that the instance can assume the role of the service. Notice am given access to all the resources not just an specific one(you can adjusted as needed)

The role

resource "aws_iam_role" "role" {
  name               = "${local.env}-role"
  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": ["ec2.amazonaws.com"]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF

}

The policy to allow access to ECR

resource "aws_iam_policy" "policy" {
  name = "${local.env}-ecr-access-policy"
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "ecr:*",
        ]
        Effect   = "Allow"
        Resource = "*"
      },
    ]
  })
}

The attachment of the policy to the role

resource "aws_iam_policy_attachment" "attach" {
  name       = "${local.env}-attach"
  roles      = ["${aws_iam_role.role.name}"]
  policy_arn = "${aws_iam_policy.policy.arn}"
}

And finally the profile the EC2 will need

resource "aws_iam_instance_profile" "profile" {
  name = "${local.env}-gitlab-runner-instance-profile"
  role = aws_iam_role.role.name
}

The EC2 instance

resource "aws_instance" "ec2" {
  ami                         = "ami-06c94f9acb4ba21b2"
  instance_type               = "t2.small"
  associate_public_ip_address = true
  key_name                    = "<key_name>"
  subnet_id                   = <subnet>
  iam_instance_profile        = aws_iam_instance_profile.profile.name
  vpc_security_group_ids      = ["<security_group>"]

  tags = {
    Environment = "dev"
  }
}
Marlon Monroy
  • 144
  • 1
  • 4
0

I think you are trying to give EC2 permission to access the ECR. For this, you need to create IAM policy for ECR and create IAM role for EC2 and attach the role with the policy.

Please refer to this code:

resource "aws_iam_role" "role" {
  name = "test-role"

  assume_role_policy = <<EOF
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Action": "sts:AssumeRole",
          "Principal": {
            "Service": "ec2.amazonaws.com"
          },
          "Effect": "Allow",
          "Sid": ""
        }
      ]
    }
EOF
}

resource "aws_iam_policy" "policy" {
  name        = "test-policy"
  description = "A test policy"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "ecr:*",
        "cloudtrail:LookupEvents"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "test-attach" {
  role       = "${aws_iam_role.role.name}"
  policy_arn = "${aws_iam_policy.policy.arn}"
}

Hope, it helps.

Deependra Dangal
  • 1,145
  • 1
  • 13
  • 36
0

You need to attach a below mentioned manual policy to your IAM role.

resource "aws_iam_role_policy" "role_policy" {
  name   = "${aws_iam_role.role.name}"
  role   = "${aws_iam_role.role.id}"
  policy = <<EOF
{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "new statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "<IAM-ROLE-ARN>"
      },
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage",
        "ecr:CompleteLayerUpload",
        "ecr:GetDownloadUrlForLayer",
        "ecr:InitiateLayerUpload",
        "ecr:PutImage",
        "ecr:UploadLayerPart"
      ]
    }
  ]
}
EOF
}
mohit
  • 2,325
  • 23
  • 48
0

Your role is created for a Service that will need the policy to use other resources, I'm not sure if this helps.

You need to create a role that something will be able to assume, ec2, sagemaker, s3, something. ECR does not assume a role as it's just a registry.

For example, I have a Sagemaker instance:

resource "aws_iam_role" "sagemaker_model" {

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "sagemaker.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF

}

Then that instance needs permission to use other Resource (ECR):

resource "aws_iam_policy" "ecr" {

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor0",
      "Effect": "Allow",
      "Action": [
        "ecr:*"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}
EOF
}

Then I attach that policy to the previous role:

resource "aws_iam_role_policy_attachment" "model_attach_ecr" {
  role       = aws_iam_role.sagemaker_model.name
  policy_arn = aws_iam_policy.ecr.arn
}

Although ECR has a specific property that it has its own access policy, you will need to allow that the previously created role can access the specific container registry by creating one aws_ecr_repository_policy:

resource "aws_ecr_repository_policy" "policy" {

  repository = <aws_ecr_repository.repo.name>
  policy     = <<EOF
{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "new statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "${aws_iam_role.sagemaker_model.arn}"
      },
      "Action": [
        "ecr:*"
      ]
    }
  ]
}
EOF
}

In this one, you will need to replace <aws_ecr_repository.repo.name> by the actual repository name.

I hope this helps.

ricoms
  • 952
  • 15
  • 22