I want to create an AWS IAM policy for multiple ECR repos
Terraform module call
module "cocos-ecr-all-repo-policy" {
count = (data.aws_region.current.name == "eu-central-1" ? 1 : 0)
source = "./modules/ecr-policies/ecr-all-repo-policy"
account_id = data.aws_caller_identity.current.account_id
}
Module
variable "account_id" {
type = string
description = "AWS account id"
}
resource "aws_iam_policy" "iam-policy" {
name = "ecr-repo-user-policy"
description = "IAM policy for ecr users"
tags = {
Creator = "terraform"
}
policy = jsonencode({
Version = "2012-10-17"
statement = [
{
sid = "EcrRepositoryAccess"
effect = "Allow"
action = [
"ecr:DescribeImages",
"ecr:ListTagsForResource",
"ecr:ListImages",
"ecr:PutImage",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:BatchDeleteImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
]
resources = [
"arn:aws:ecr:*:${var.account_id}:repository/repo1/*",
"arn:aws:ecr:*:${var.account_id}:repository/repo2/*",
]
},
{
sid = "EcrToken"
effect = "Allow"
actions = [
"ecr:GetAuthorizationToken",
]
resources = [
"*",
]
}
]
})
}
Plan returns this
Terraform will perform the following actions:
# module.cocos-ecr-all-repo-policy[0].aws_iam_policy.iam-policy will be created
+ resource "aws_iam_policy" "iam-policy" {
+ arn = (known after apply)
+ description = "IAM policy for ecr users"
+ id = (known after apply)
+ name = "ecr-repo-user-policy"
+ path = "/"
+ policy = jsonencode(
{
+ Statement = [
+ {
+ Action = [
+ "ecr:DescribeImages",
+ "ecr:ListTagsForResource",
+ "ecr:ListImages",
+ "ecr:PutImage",
+ "ecr:GetDownloadUrlForLayer",
+ "ecr:BatchGetImage",
+ "ecr:BatchCheckLayerAvailability",
+ "ecr:BatchDeleteImage",
+ "ecr:InitiateLayerUpload",
+ "ecr:UploadLayerPart",
+ "ecr:CompleteLayerUpload",
]
+ Effect = "Allow"
+ Resources = [
+ "arn:aws:ecr:*:<AWS account id>:repository/repo1/*",
+ "arn:aws:ecr:*:<AWS account id>:repository/repo2/*",
]
+ Sid = "EcrRepositoryAccess"
},
+ {
+ Actions = [
+ "ecr:GetAuthorizationToken",
]
+ Effect = "Allow"
+ Resources = [
+ "*",
]
+ Sid = "EcrToken"
},
]
+ Version = "2012-10-17"
}
)
+ policy_id = (known after apply)
+ tags = {
+ "Creator" = "terraform"
}
+ tags_all = {
+ "Creator" = "terraform"
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
Apply returned error message:
Error: error creating IAM policy ecr-repo-user-policy: MalformedPolicyDocument: Syntax errors in policy.
Creation of policy with AWS Console GUI works fine.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"ecr:DescribeImages",
"ecr:ListTagsForResource",
"ecr:ListImages",
"ecr:PutImage",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload"
],
"Resource": [
"arn:aws:ecr:*:<AWS account id>:repository/repo1/*",
"arn:aws:ecr:*:<AWS account id>:repository/repo2/*"
]
},
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": "ecr:GetAuthorizationToken",
"Resource": "*"
}
]
}
The problem is with first statement to create ECR repo permissions. I tried different changes to terraform code, un/capitalization of key words like Action, add/remove comma after last line of ressource and action blocks. Commenting out second statement did not change anything. Nothing did help. Any help would be appreciated.
It's because of syntax errors in your policy doc
All the keys in this policy doc should be in Camelcase and use singular nouns instead of plural, for example, it's Resource
instead of resources
. You can also find a short example here at the official doc as well https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy
So, Your policy should be like this
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "EcrRepositoryAccess"
Effect = "Allow"
Action = [
"ecr:DescribeImages",
"ecr:ListTagsForResource",
"ecr:ListImages",
"ecr:PutImage",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:BatchDeleteImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload",
]
Resource = [
"arn:aws:ecr:*:<AWS account id>::repository/repo1/*",
"arn:aws:ecr:*:<AWS account id>::repository/repo2/*",
]
},
{
Sid = "EcrToken"
Effect = "Allow"
Action = [
"ecr:GetAuthorizationToken",
]
Resource = [
"*",
]
}
]
})