Open jamrobi2 opened 2 years ago
Able to reproduce this issue with code like
resource "aws_iam_policy" "blah" {
name = "${terraform.workspace}_blah"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParametersByPath",
"ssm:GetParameter"
],
"Resource": [
...
]
},
{
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken",
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage"
],
"Resource": "*"
}
]
}
EOF
}
resource "aws_iam_role_policy" "blah" {
name = "${terraform.workspace}_blah"
role = aws_iam_role.blah.id
policy = aws_iam_policy.blah.policy
}
Running plan
and apply separately, I think it saves the plan file and then passes it to the apply
.
Getting:
β Error: Provider produced inconsistent final plan
β
β When expanding the plan for aws_iam_role_policy.blah to include new
β values learned so far during apply, provider
β "registry.terraform.io/hashicorp/aws" produced an invalid new value for
β .policy: was cty.StringVal("{\n \"Version\": \"2012-10-17\",\n
β \"Statement\": [\n {\n \"Effect\": \"Allow\",\n
β \"Action\": [\n \"ssm:GetParametersByPath\",\n
β \"ssm:GetParameter\"\n ],\n \"Resource\": [\n...]\n
β },\n {\n \"Effect\": \"Allow\",\n \"Action\": [\n
β \"ecr:GetAuthorizationToken\",\n
β \"ecr:BatchCheckLayerAvailability\",\n
β \"ecr:GetDownloadUrlForLayer\",\n \"ecr:BatchGetImage\"\n
β ],\n \"Resource\": \"*\"\n }\n ]\n}\n\n"), but now
β cty.StringVal("{\"Statement\":[{\"Action\":[\"ssm:GetParametersByPath\",\"ssm:GetParameter\"],\"Effect\":\"Allow\",\"Resource\":[...]},{\"Action\":[\"ecr:GetAuthorizationToken\",\"ecr:BatchCheckLayerAvailability\",\"ecr:GetDownloadUrlForLayer\",\"ecr:BatchGetImage\"],\"Effect\":\"Allow\",\"Resource\":\"*\"}],\"Version\":\"2012-10-17\"}").
β
β This is a bug in the provider, which should be reported in the provider's
β own issue tracker.
I cleaned up these two strings into properly formatted json and they are identical OBJECTS, but the strings are different because of ordering of keys among other things.
According to
policy
- (Required) The inline policy document. This is a JSON formatted string.
When we do
resource "aws_iam_role_policy" "blah" {
name = "${terraform.workspace}_blah"
role = aws_iam_role.blah_ec2.id
policy = aws_iam_policy.blah.policy
}
the policy = aws_iam_policy.blah.policy
part is passing a JSON string..
I had the idea of trying to canonicalize the JSON (sort of object keys and sort the values within any arrays that are technically sets, not lists)
I thought of trying to run something like the following in a shell script null_resource
:
jq --sort-keys '{
Version: .Version,
Statement: [.Statement[] | {
Effect: .Effect,
Action: (if (.Action | type) == "array" then (.Action | sort) else .Action end),
Resource: (if (.Resource | type) == "array" then (.Resource | sort) else .Resource end)
}] | sort_by("\(.Effect).\((if (.Action | type) == "array" then (.Action | sort) else .Action end))\((if (.Resource | type) == "array" then (.Resource | sort) else .Resource end))")
}'
Of course that only covers a subset of the policy JSON schema, and IDK if it will even work, but thought I'd share the idea. if we give it a try i'll post an update.
Community Note
Terraform CLI and Terraform AWS Provider Version
Affected Resource(s)
Terraform Configuration Files
Please include all Terraform configurations required to reproduce the bug. Bug reports without a functional reproduction may be closed without investigation.
Debug Output
Expected Behavior
The tf should apply without errors
Actual Behavior
It does not deploy, it throws the error;
Steps to Reproduce
terraform apply