terraform-provider-aws: MalformedPolicyDocument: Invalid principal in policy: "AWS" [Only when Principal is a ROLE.]

https://github.com/terraform-providers/terraform-provider-aws/issues/1388

The documentation specifically says this is allowed: https://www.terraform.io/docs/providers/aws/d/iam_policy_document.html#example-with-multiple-principals

data "aws_caller_identity" "caller_identity" {}

data "aws_iam_policy_document" "trust-assume-role-policy" {
  statement {
    effect = "Allow"

    actions = [
      "sts:AssumeRole",
    ]

    principals {
      type = "Service"

      identifiers = [
        "ec2.amazonaws.com",
      ]
    }

    principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::${data.aws_caller_identity.caller_identity.account_id}:role/nodes.${var.env}"]
    }
  }
}

Terraform message: Assume Role Policy: MalformedPolicyDocument: Invalid principal in policy

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 21
  • Comments: 15 (3 by maintainers)

Most upvoted comments

I don’t think this is an issue with Terraform or the AWS provider. If you try creating this role in the AWS console you would likely get the same error. I’ve experienced this problem and ended up here when searching for a solution. What I ultimately discovered is that you get this error if the role you are referencing doesn’t actually exist. The reason is that the role ARN is translated to the underlying unique role ID when it is saved. See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html

If your Principal element in a role trust policy contains an ARN that points to a specific IAM role, then that ARN is transformed to the role’s unique principal ID when the policy is saved.

I created the referenced role just to test, and this error went away.

@yanirj … it works, but using sleep arrangements is not really a ‘production’ level solution to fill anyone with confidence. Hope someone fixes this …

I encountered this today when I create a user and add that user arn into the trust policy for an existing role. I was able to recreate it consistently. The error I got was:

Error: Error Updating IAM Role (test_cert) Assume Role Policy: MalformedPolicyDocument: Invalid principal in policy: “AWS”:“arn:aws:iam::xxx:user/test_user”

In order to workaround it I added a local-exec to the user creation (thankfully I have a library module that we use to create all users). Note that I can safely use the linux "sleep command as all our terraform runs inside a linux container. Others may want to use the terraform time_sleep resource. https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep

resource "aws_iam_user" "my_user" {
  name          = "svc_terraform_${var.name}"
  force_destroy = var.force_destroy
  tags          = var.tags

  provisioner "local-exec" {
    # This is because when we create a user and immediately add it into the trust policy of a role
    # it can fail. IAM resources are all handled via us-east-1 and have to get replicated/cached etc
    # see https://docs.aws.amazon.com/IAM/latest/UserGuide/troubleshoot_general.html#troubleshoot_general_eventual-consistency
    # I thought that waiting for the user to exist would fix this, but it doesn't
    # command = "aws iam wait user-exists --user-name ${aws_iam_user.my_user.name}"
    #
    # I also tried using an explicit AWS provider for us-east-1, but that didn't seem to have any effect.
    # Sleeping seems to work, but I'm sure if IAM is delayed then it could break. Rerunning the plan solves this,
    # but I wanted to find something that makes this a non-problem most of the time. 

    command = "sleep 10s"
  }
}

Theoretically this could happen on other IAM resources (roles, policies etc) but I’ve only experienced it with users so far.

Could you please try adding policy as json in role itself.I was getting the same error. I tried this and it worked Something Like this -

resource "aws_iam_role" "test_role" {
  name = "test_role"

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

  tags = {
    tag-key = "tag-value"
  }
}.