terraform-provider-aws: Order is lost for data `aws_iam_policy_document` when applied to S3 buckets, iam roles, kms keys, etc
Community Note
- Please vote on this issue by adding a š reaction to the original issue to help the community and maintainers prioritize this request
- Please do not leave ā+1ā or other comments that do not add relevant new information or questions, they generate extra noise for issue followers and do not help prioritize the request
- If you are interested in working on this issue or have submitted a pull request, please leave a comment
See also #21968
Terraform Version
ā terraform --version
Terraform v0.12.20
+ provider.aws v2.46.0
Affected Resource(s)
aws_ecr_repository_policyaws_kms_keyaws_s3_bucketaws_launch_configurationaws_lb_listeneraws_codeartifact_domain_pernission_policy
Terraform Configuration Files
If running locally, please add your own real roles to local.secrets_roles otherwise the kms policy will fail.
provider "aws" {
region = "us-east-1"
}
data "aws_caller_identity" "current" {}
locals {
id = data.aws_caller_identity.current.account_id
secrets_roles = [
"asnip",
"esnip",
"lsnip",
"psnip",
"wsnip",
"csnip",
# "default",
]
secrets_roles_arns = sort([
for role in local.secrets_roles :
"arn:aws:iam::${local.id}:role/${role}"
])
secrets_admin = [
"arn:aws:iam::${local.id}:role/sre"
]
}
data "aws_iam_policy_document" "secrets" {
policy_id = "secrets-policy"
statement {
sid = "Enable IAM User Permissions"
effect = "Allow"
resources = ["*"]
actions = [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion",
]
principals {
type = "AWS"
identifiers = local.secrets_admin
}
}
statement {
sid = "Allow use of the key"
effect = "Allow"
resources = ["*"]
actions = [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey",
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
]
principals {
type = "AWS"
identifiers = local.secrets_roles_arns
}
}
}
resource "aws_kms_key" "secrets_test" {
description = "test Default key for secrets encryption."
key_usage = "ENCRYPT_DECRYPT"
is_enabled = true
enable_key_rotation = false
policy = data.aws_iam_policy_document.secrets.json
}
resource "aws_kms_alias" "secrets_test" {
name = "alias/secrets-test"
target_key_id = aws_kms_key.secrets_test.key_id
}
output "role_arns" {
value = local.secrets_roles_arns
}
output "policy_json" {
value = data.aws_iam_policy_document.secrets.json
}
output "key_policy_json" {
value = aws_kms_key.secrets_test.policy
}
In terraform console
local.secrets_roles_arns is alphabetical
[
"arn:aws:iam::1234567890:role/asnip",
"arn:aws:iam::1234567890:role/csnip",
"arn:aws:iam::1234567890:role/esnip",
"arn:aws:iam::1234567890:role/lsnip",
"arn:aws:iam::1234567890:role/psnip",
"arn:aws:iam::1234567890:role/wsnip",
]
data.aws_iam_policy_document.secrets.json is reverse alphabetical which is expected (https://github.com/terraform-providers/terraform-provider-aws/issues/6107)
...
"Principal": {
"AWS": [
"arn:aws:iam::1234567890:role/wsnip",
"arn:aws:iam::1234567890:role/psnip",
"arn:aws:iam::1234567890:role/lsnip",
"arn:aws:iam::1234567890:role/esnip",
"arn:aws:iam::1234567890:role/csnip",
"arn:aws:iam::1234567890:role/asnip"
]
}
...
aws_kms_key.secrets_test.policy returns the same output which is perfect
"Principal": {
"AWS": [
"arn:aws:iam::1234567890:role/wsnip",
"arn:aws:iam::1234567890:role/psnip",
"arn:aws:iam::1234567890:role/lsnip",
"arn:aws:iam::1234567890:role/esnip",
"arn:aws:iam::1234567890:role/csnip",
"arn:aws:iam::1234567890:role/asnip"
]
}
After applying the above, I added a default role to local.secrets_roles and I see this in the plan
...
~ Principal = {
~ AWS = [
- "arn:aws:iam::1234567890:role/asnip",
- "arn:aws:iam::1234567890:role/psnip",
"arn:aws:iam::1234567890:role/wsnip",
- "arn:aws:iam::1234567890:role/csnip",
- "arn:aws:iam::1234567890:role/esnip",
+ "arn:aws:iam::1234567890:role/psnip",
"arn:aws:iam::1234567890:role/lsnip",
+ "arn:aws:iam::1234567890:role/esnip",
+ "arn:aws:iam::1234567890:role/default",
+ "arn:aws:iam::1234567890:role/csnip",
+ "arn:aws:iam::1234567890:role/asnip",
]
}
...
Debug Output
Expected Behavior
Order should be retained. I wouldnāt mind the reverse alphabetical order at the very least.
Actual Behavior
Random order
Steps to Reproduce
- Create a few roles (or reuse them)
- Set the
local.secrets_roleswith actual roles terraform apply- Change
local.secrets_rolesby adding another existing role terraform planand you will see random order
Important Factoids
I edited a policy in AWS console, changed the order of principal aws to alphabetical, saved it, and also saw a random order. Perhaps it is the AWS API that is reordering them?
References
Workaround
After upgrading to Terraform 0.14.x, my most recent workaround is by supplying an output
output "key_policy_json" {
value = data.aws_iam_policy_document.secrets.json
}
Then in the terraform plan or terraform apply, it will hide all the unchanged and only show the few that changed.
~ {
~ Principal = {
~ AWS = [
# (250 unchanged elements hidden)
"arn:aws:iam::1234567890:role/csnip",
+ "arn:aws:iam::1234567890:role/default",
"arn:aws:iam::1234567890:role/esnip",
# (125 unchanged elements hidden)
]
}
# (4 unchanged elements hidden)
},
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 256
- Comments: 45 (13 by maintainers)
Hi all š Just letting you know that this is issue is featured on this quarters roadmap. We will be a looking for a pattern to implement that can help resolve both this and related issues.
If a PR exists to close the issue a maintainer will review and either make changes directly, or work with the original author to get the contribution merged. If you have written a PR to resolve the issue please ensure the āAllow edits from maintainersā box is checked. Thanks for your patience and we are looking forward to getting this merged soon!
This is the best write-up I have see for what I think is going on here: https://github.com/hashicorp/terraform-plugin-framework/issues/70. The
suppressEquivalentAwsPolicyDiffsDiffSuppressFunccorrectly returns that 2 policy documents are equal but the value of the attribute set during resourceReadhas elements in a different order and the Terraform CLI reports a change.Note to (future) self - Related:
A solution is to add a helper like
so that the new policy value is only set if itās not equivalent to the prior value.
Iām experiencing a similar problem with Terraform 0.15.4 .
Terraform 0.15.4 will now report the changes made outside of Terraform as part of the plan result. Some list orders is not retained, so Terraform always reports list orders have been changed like below.
This problem has no real impact, but the plan results are unnecessarily long, and visibility is degraded.
Even though the api returns it in a random order, couldnāt the apply save the policy in alphabetical order in the tfstate and then have the plan retrieve it from the aws api and then alphabetize it again to diff it thereby avoiding the reorder shown in the current diff?
This issue affects
1.0as well.This issue does not appear to be limited to aws_kms_key, it may be for assume_role_policy attributes in general. As of Terraform 0.15.4 this also occurs for the assume_role_policy attribute of aws_iam_role resources if there is >1 federated principal defined. Running
terraform planover and over on an unchanging AWS resource randomly calculates different diffs in the āObjects have changed outside of Terraformā section.I think all thatās needed is a smarter diff function for
policyattributes in various AWS resources. So that first of all both local and remote policy documents are normalised by sorting principals and actions, and by wrapping singular items in lists, and only then the two normalised policies should be structurally compared. That would have eliminated almost all false drifts that we are seeing on a daily basis. I am currently upgrading to Terraform 1.0 and this non-deterministic ordering results in drifts being reported all the time, even after an explicitterraform refresh. This is going to be an even bigger source of noise from now on.Just another āme, tooā. This is tehncially AWSās fault if itās reordering lists inside JSON; thatās supposed to be a no-no. But since these particular lists are semantically treated as sets, probably Terraform should special-case the comparison so that it doesnāt care about order.
we noticed similar issue as well
It still affects 1.0.1 as well. For me all resources (usually policies) which has any ARN list like the example below are affected:
It still occurs on every plan for a random selection of resources even after applying changes but Iāll be switching to one of the newly reported defects that cover my specific remaining symptoms as suggested by YakDriver.
Thanks all for the great work on the larger issue group, itās clearly been a lot of work!
This functionality has been released in v3.70.0 of the Terraform AWS Provider. Please see the Terraform documentation on provider versioning or reach out if you need any assistance upgrading.
For further feature requests or bug reports with this functionality, please create a new GitHub issue following the template. Thank you!
Ordering is easy butā¦
āOrderā in the context of this issue has two caveats:
aws_iam_policy_document, we have some say in the order because weāre generating the JSON. But, with the plainpolicyargument set tojsonencode()or a heredoc (š), we donāt do anything with the order. Thatās not to say we couldnāt but so far we havenāt crossed that bridge. Hopefully, we wonāt have to.What are we solving?
I see there being two problems:
Our approach will be to fix # 1 and then see where weāre at with # 2. Currently the two problems are intertwined in the issues to the point they are convulting each other. Once pain points are alleviated (hopefully) with #21968, weāll need your input to determine what problems still remain.
Wouldnāt automagically sorting lists in AWS API response AND expected principals before comparing solve this? This should be easy š
Confirming it works like that for ANY policy. Suggestion about sorting principals before storing and comparing should do the trick here.
@nitrocode can you change the title so itās not misleading?
May not even be limited to
assume_role_policy. Iām also seeing this on thepolicyattribute of anaws_s3_bucket. (Iām also using thejsonencodeapproach.)Same.
Using Terraform 0.15.4 and applying for a directory with 30+ ecr repository resources with policies. Those policies are having their Principals section randomly sorted by AWS IAM, but neither
lifecycle ignore_changesnorterraform refreshget rid of the changes on subsequent applies, which is somewhat difficult since the output stream is very verbose and makes it harder to grok the updated changes.After looking into this issue and looking into the jen20 library for awspolicyequivalency and https://github.com/hashicorp/terraform-provider-aws/blob/main/aws/resource_aws_kms_key.go#L205 nothing in Terraform was causing the policy re ordering and the Terraform outputs looked as Iād expect.
As it turns out, KMS just saves in a random order. This can be replicated with a plain old
aws_kms_key(read: not related to the loops/lists as above) passing in a policy, and later appending a new principal.Can also replicate this in the AWS console:
@anthonyAdhese We hoped to alleviate the majority of a pain points with this push. I ask that you give 3.70.0 a try when it is available. If youāre still seeing issues, please open a new issue! We will need a complete config to be able to reproduce the issue.
This issue is still present on
1.0.9Seeing this on version
1.0.5withaws_iam_rolein Principal > Service.I donāt think this is an issue with the version of Terraform, but the version of the AWS provider itself, as this is wholly within the
aws_iam_policy_document. Until this is fixed here, upgrading Terraform will not help?same issue on
aws_ecr_repository_policyWe skipped 0.15 and went to 1.0 but I can confirm that on 0.14 I did not see this issue and after upgrading to 1.0 I now see this in a number of places. Sorting the lists in the terraform code does not help.
Same issue here, this makes the idea of checking the plan nearly impossible without some programmatic filtering on the client side, as this bug generates thousands of lines of redundant plan code (in our case) and everything else gets lost in the noise.
Terraform 15.5
Same issue here with
0.14.11andaws_codeartifact_domain_permissions_policyThe form of the defect described here https://github.com/hashicorp/terraform-provider-aws/issues/11801#issuecomment-848984552 is still occurring.
hi any updates here?
How AWS stores resources/objects in their backend is quite different than what they present to users, and for many years Iāve suspected that when appropriate they either store some data in unordered sets or have code that somewhere along the line treats some data as unordered lists. Unfortunately JSON does not support unordered sets, resulting in what should be an unordered list instead being returned to us as a reordered list. This phenomenon is not unique to AWS, and can sometimes be seen when diffing JSON-formatted Terraform statefiles.
Instructing Terraform to ignore reordering is one solution, however IMO itās potentially worth natively supporting the concept unordered sets. As for identifying them, perhaps we can utilize the results of existing unit tests?
This issue is still present on
1.0.7As @chroju points out the issue is just state change detection and not the execution plan
So you often see
It feels like the distinction between an ordered list and an unordered set could be first-class consideration in both to handle all these cases where dubious APIs by AWS and others return things in random order
It might help if a core Hashicorp person could explain the rationale this is only in the plan phase as it seems intentional.
Mitigations could include
Same problem here with an S3 Bucket Policy. Terraform 15.5, hashicorp/aws v3.44.0
even the AWS UI does this ⦠If you refresh the KMS key view page a couple of times you will notice the principals in the policy returned in random orders.
can confirm this same issue exists in 1.0.2 as well. Ordering is not respected and subsequent runs will throw warnings for differing āchangesā each time, even though no actual changes have been made.
+1 for this, seeing it in both KMS resource-based-policies and IAM resources with terraform 0.15.4.