1
votes

Hi AWS and Terraform experts, I was kinda generating the KMS and IAM association that was built manually by our former colleague, I'm getting an issue to completing the copy of kms policy stated below:

{
"Version": "2012-10-17",
"Statement": [
    {
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::12345678912345:root"
        },
        "Action": "kms:*",
        "Resource": "*"
    },
    {
        "Effect": "Allow",
        "Principal": {
            "AWS": "ALSKDJFHGNVBCMXJDH0987"
        },
        "Action": "kms:Decrypt",
        "Resource": "*"
    }
]

}

This ALSKDJFHGNVBCMXJDH0987 is an IAM Role which was I believe transformed by AWS console (not yet sure why)

  {
        "Effect": "Allow",
        "Principal": {
            "AWS": "ALSKDJFHGNVBCMXJDH0987"
        },
        "Action": "kms:Decrypt",
        "Resource": "*"
    }

I'm getting this error using the created terraform script I made:

Error: MalformedPolicyDocumentException: Policy contains a statement with one or more invalid principals.
status code: 400, request id: alsknldkj2-assd-3333-0sdc-askdjaksdjn2

on main.tf line 84, in resource "aws_kms_key" "secrets":
84: resource "aws_kms_key" "secrets" {

Is there something wrong with the sequence? or I'm missing anything?. Attached here is the terraform code I used:

data "template_file" "my-lambda-policy" {
 template = "${file("policy/lambda.json")}"
  vars = {
      SWAG = var.AWS-SWAG
      STUDENT-BELONGS = var.STUDENT
      STUDENT-TEACHER = var.TEACHER
      ROOM = var.CLASSROOM
  }
}

resource "aws_iam_policy" "my-lambda-pol" {
  name = "my-lambda-policy"
  policy = data.template_file.my-lambda-policy.rendered
}

data "template_file" "my-my-lambda-pol2" {
  template = "${file("policy/lambda2.json")}"
}

resource "aws_iam_policy" "my-lambda-pol2" {
  name = "my-my-lambda-pol2"
  policy = data.template_file.my-my-lambda-pol2.rendered
}

data "template_file" "my-lambda-to-my-kms-policy" {
  template = "${file("policy/kms-lambda.json")}"
  vars = {
      SWAG = var.AWS-SWAG
      KMS_KEY_ID = aws_kms_key.mysecret.id
  }
}

resource "aws_iam_policy" "lambda-to-kms" {
  name = "my-lambda-to-my-kms-policy"
  policy = data.template_file.my-lambda-to-my-kms-policy.rendered
}

resource "aws_iam_role" "the-lambda-role" {
  name = "{STUD_CHAIR}-${STU_SEAG}-${STUDENT-BELONGS}-${STUDENT-TEACHER}"
  assume_role_policy = <<EOF
{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": {
            "Service": "lambda.amazonaws.com"
         },
         "Action": "sts:AssumeRole"
      }
   ]
}
EOF
}

resource "aws_iam_role_policy_attachment" "my-lambda-policy_attachment" {
  policy_arn = aws_iam_policy.my-lambda-pol.arn
  role = aws_iam_role.the-lambda-role.name
}

resource "aws_iam_role_policy_attachment" "my-lambda-pol2_attachment" {
  policy_arn = aws_iam_policy.my-lambda-pol2.arn
  role = aws_iam_role.the-lambda-role.name
}

resource "aws_iam_role_policy_attachment" "kms-attachment" {
  depends_on = [aws_kms_key.mysecret]
  policy_arn = aws_iam_policy.lambda-to-kms.arn
  role = aws_iam_role.the-lambda-role.name
}

data "template_file" "my-kms-policy" {
  template = "${file("policy/my-kms-policy.json")}"
  vars = {
      STUD_CHAIR= "${var.CHAIR}"
      STU_SWAG = "${l{var.SWAG}}"
      STUDENT-BELONGS = "${var.STUDENT}"
      STUDENT-TEACHER = "${var.TEACHER}"
      ROOM = "${var.CLASSROOM}"
  }
}

resource "aws_kms_key" "mysecret" {
  description = "KMS Key for ${var.STUDENT}-${var.TEACHER}-key-${var.CLASSROOM}"
  policy = data.template_file.my-kms-policy.rendered
  depends_on = [aws_iam_role.the-lambda-role]
}

resource "aws_kms_alias" "mysecret" {
  name = "alias/${var.STUDENT}-${var.TEACHER}-key-${var.CLASSROOM}"
  depends_on = [aws_iam_role.the-lambda-role]
  target_key_id = aws_kms_key.mysecret.key_id
}

this is what inside of my-kms-policy.json

{
"Version": "2012-10-17",
"Statement": [
    {
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::${ROOM}:root"
        },
        "Action": "kms:*",
        "Resource": "*"
    },
    {
        "Effect": "Allow",
        "Principal": {
            "AWS": "arn:aws:iam::${ROOM}:role/${STUD_CHAIR}-${STU_SEAG}-${STUDENT-BELONGS}-${STUDENT-TEACHER}"
        },
        "Action": "kms:Decrypt",
        "Resource": "*"
    }
]
}
1
The ALSKDJFHGNVBCMXJDH0987 principal value is created when the IAM role ARN that was previously referenced has been deleted. Are you sure your IAM Role that you're trying to permission exists?GreenyMcDuff

1 Answers

1
votes

Workaround

A workaround is to run terraform apply twice.

Reason

When recreating an IAM role the policy referencing this role needs to be updated for reasons described here:

https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user.html

If your Principal element contains the ARN for a specific IAM role or user, then that ARN is transformed to a unique principal ID when the policy is saved. This helps mitigate the risk of someone escalating their permissions by removing and recreating the role or user. You don't normally see this ID in the console because there is also a reverse transformation back to the ARN when the trust policy is displayed. However, if you delete the role or user, then the principal ID appears in the console because AWS can no longer map it back to an ARN. Therefore, if you delete and recreate a user or role referenced in a trust policy's Principal element, you must edit the role to replace the ARN.

Running Terraform the first time will recreate the IAM role and that way break the policy. Running it the second time will correct the policy, by adding the newly created reference to the IAM role.