Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

while setting policy (), encountered: Error parsing policy: Unknown error parsing statement #22944

Closed
DenisBY opened this issue Feb 4, 2022 · 13 comments
Assignees
Labels
bug Addresses a defect in current functionality. service/iam Issues and PRs that pertain to the iam service.

Comments

@DenisBY
Copy link

DenisBY commented Feb 4, 2022

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

Terraform CLI and Terraform AWS Provider Version

$ terraform -v
Terraform v1.0.11
on linux_amd64
+ provider registry.terraform.io/hashicorp/aws v3.74.0
+ provider registry.terraform.io/hashicorp/random v3.1.0
+ provider registry.terraform.io/hashicorp/template v2.2.0

Affected Resource(s)

aws_iam_policy

Terraform Configuration Files

Please include all Terraform configurations required to reproduce the bug. Bug reports without a functional reproduction may be closed without investigation.

variable "ssm_param_path" {
  type        = list(string)
  default     = []
}

data "aws_iam_policy_document" "iam_policy_ssm" {
  dynamic "statement" {
    for_each = toset(var.ssm_param_path)
    content {
      actions   = ["ssm:GetParameter*"]
      resources = ["arn:aws:ssm:eu-central-1:123456789012:parameter${statement.key}"]
    }
  }
}

resource "aws_iam_policy" "iam_policy_ssm" {
  name        = "ssm-param-store-${local.name}"
  description = "ssm-param-store-${local.name}"

  policy = data.aws_iam_policy_document.iam_policy_ssm.json
}

Debug Output

I don't see anything related to this issue in debug output.

Expected Behavior

State applied

Actual Behavior

│ Error: while setting policy (), encountered: Error parsing policy: Unknown error parsing statement
│ 
│   with module.docker-image-base.aws_iam_policy.iam_policy_ssm,
│   on .terraform/modules/docker-image-base/codebuild/iam.tf line 56, in resource "aws_iam_policy" "iam_policy_ssm":
│   56: resource "aws_iam_policy" "iam_policy_ssm" {

Steps to Reproduce

  1. terraform apply

Important Factoids

Initially, when I applied the sate, the module didn't have the part with aws_iam_policy_document, I used 'plain' json instead. Later I switched to use aws_iam_policy_document to generate it dynamically and yesterday I wanted to apply the state again to update few things. I applied the state without setting ssm_param_path so default value [] has been used. After this I can't apply it anymore with any value. I use the same module in other states but they have some value set for ssm_param_path and I don't have this issue there.

part of tfstate looks like this:

  "resources": [
    {
      "module": "module.docker-image-base",
      "mode": "data",
      "type": "aws_iam_policy_document",
      "name": "iam_policy_ssm",
      "provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
      "instances": [
        {
          "schema_version": 0,
          "attributes": {
            "id": "561002259",
            "json": "{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": null\n}",
            "override_json": null,
            "override_policy_documents": null,
            "policy_id": null,
            "source_json": null,
            "source_policy_documents": null,
            "statement": null,
            "version": "2012-10-17"
          },
          "sensitive_attributes": []
        }
      ]
@github-actions github-actions bot added needs-triage Waiting for first response or review from a maintainer. service/iam Issues and PRs that pertain to the iam service. labels Feb 4, 2022
@DenisBY
Copy link
Author

DenisBY commented Feb 4, 2022

I had to use terraform state rm module.docker-image-base.aws_iam_policy.iam_policy_ssm to be able to re-apply the state.
I also removed module.docker-image-base.data.aws_iam_policy_document.iam_policy_ssm before removing state above, not sure if it was needed.

@justinretzolk justinretzolk added bug Addresses a defect in current functionality. and removed needs-triage Waiting for first response or review from a maintainer. labels Feb 16, 2022
@justinretzolk
Copy link
Member

Hey @DenisBY 👋 Thank you for taking the time to raise this! I'm marking this as a bug so that we can look into it when time allows, but wanted to touch on a couple of things that I noticed. Apologies in advance if any of this is already information you had!

I used the following simplified configuration to test what the resulting policy would look like after the dynamic block:

variable "ssm_param_path" {
  type    = list(string)
  default = []
}

data "aws_iam_policy_document" "iam_policy_ssm" {
  dynamic "statement" {
    for_each = toset(var.ssm_param_path)
    content {
      actions   = ["ssm:GetParameter*"]
      resources = ["arn:aws:ssm:eu-central-1:123456789012:parameter${statement.key}"]
    }
  }
}

output "json" {
  value = data.aws_iam_policy_document.iam_policy_ssm.json
}

Upon running a terraform plan with some value set for the ssm_param_path, the output was as follows:

Changes to Outputs:
  + json = jsonencode(
        {
          + Statement = [
              + {
                  + Action   = "ssm:GetParameter*"
                  + Effect   = "Allow"
                  + Resource = "arn:aws:ssm:eu-central-1:123456789012:parametersomepath"
                  + Sid      = ""
                },
            ]
          + Version   = "2012-10-17"
        }
    )

On the other hand, not setting a value for ssm_param_path led to the following output:

Changes to Outputs:
  + json = jsonencode(
        {
          + Statement = null
          + Version   = "2012-10-17"
        }
    )

This makes it a bit more clear as to why the policy showed as invalid, but overall, I think there's maybe more to look into with regards to why later applies with a valid value passed to ssm_param_path did not succeed; perhaps there's additional validation that needs to happen to prevent something like this; I'll leave that to the team to investigate further.

In the interim, my initial thought would be to update the ssm_param_path variable to not set a default value. This would mean that if a value was not explicitly set, the configuration would fail to run, and would prevent this situation from occurring again. For what it's worth, you could also set the variable type to set(string), which would eliminate the need for using toset() in the for_each argument of the dynamic block.

@miiichael
Copy link

For a slightly simpler reproduction, try:

data "aws_iam_policy_document" "maybe_empty" {
  statement { # the specific statement is immaterial here
    actions = [ "ssm:SendCommand" ]
    resources = [ "*" ]
  }
}

resource "aws_iam_policy" "tf_go_spang" {
  name        = "tf-go-spang"
  policy      = data.aws_iam_policy_document.maybe_empty.json
}

Plan+apply this. Then comment out the single statement, and plan+apply again. Terraform will then attempt (but fail) to update the policy in-place.

Tested just now with TF 1.1.7 and AWS provider 4.4.0.

@miiichael
Copy link

Trying various version of the AWS provider, I notice behaviour changed between 3.68.0 and 3.69.0.

3.68 (and the earlier versions I tried) allow you to recover without having to perform surgery on the state to remove resource(s) TF chokes on; later versions do not.

@theherk
Copy link
Contributor

theherk commented Jul 5, 2022

I just ran into this same condition. I used a policy using source_policy_documents only and the list was empty. The was able to recover by removing it from the state.

I should add that was with provider v4.18.0.

@YakDriver
Copy link
Member

This should be fixed with #23060 (specifically the new version of hashicorp/awspolicyequivalence). Let us know if you're still having issues with v4.23.0, when it comes out.

@YakDriver
Copy link
Member

I will close this on ~August 4, 2022 if I've not heard back that there are still issues in v4.23.0.

@paololazzari
Copy link

This isn't fixed. Seeing same issue with 4.27.0

@paololazzari
Copy link

paololazzari commented Aug 24, 2022

│ Error: while setting policy (), encountered: parsing policy 1: parsing statement 1: 3 errors(s) decoding
│ * '[0].Condition[test]' expected a map, got 'string'
│ * '[0].Condition[values]' expected a map, got 'slice'
│ * '[0].Condition[variables]' expected a map, got 'string'

even if I remove the policy document, the error persist. this has basically corrupted my terraform state apparently, and I can't remove it from the state because it doesn't show up. so I'm stuck now

@paololazzari
Copy link

related #22895

@jar-b
Copy link
Member

jar-b commented Oct 28, 2022

I believe #23060 has resolved the issue relating to empty statements (other setting policy errors unrelated to empty statements may still exist). I've included a minimal config and reproduction details below.

To allow time for feedback on the reproduction, we're going to leave this issue open for now. If no objections are received we will close this as completed in the near future.

Terraform Config

Show
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
      #version = "4.22.0"
    }
  }
}

provider "aws" {}

data "aws_iam_policy_document" "not_empty" {
  statement {
    actions   = ["sts:GetCallerIdentity"]
    resources = ["*"]
  }
}

data "aws_iam_policy_document" "empty" {}

resource "aws_iam_policy" "repro" {
  name   = "empty_policy_apply_repro"
  # uncomment this on first apply so valid document is created
  policy = data.aws_iam_policy_document.not_empty.json
  # uncomment this on second apply to observe failed updated
  #policy = data.aws_iam_policy_document.empty.json
}

Reproduction

$ terraform -v
Terraform v1.3.3
on darwin_arm64
+ provider registry.terraform.io/hashicorp/aws v4.37.0
  1. Create a valid policy.
Show
$ terraform apply -auto-approve
data.aws_iam_policy_document.empty: Reading...
data.aws_iam_policy_document.not_empty: Reading...
data.aws_iam_policy_document.empty: Read complete after 0s [id=1132004489]
data.aws_iam_policy_document.not_empty: Read complete after 0s [id=2969320202]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # aws_iam_policy.repro will be created
  + resource "aws_iam_policy" "repro" {
      + arn       = (known after apply)
      + id        = (known after apply)
      + name      = "empty_policy_apply_repro"
      + path      = "/"
      + policy    = jsonencode(
            {
              + Statement = [
                  + {
                      + Action   = "sts:GetCallerIdentity"
                      + Effect   = "Allow"
                      + Resource = "*"
                      + Sid      = ""
                    },
                ]
              + Version   = "2012-10-17"
            }
        )
      + policy_id = (known after apply)
      + tags_all  = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.
aws_iam_policy.repro: Creating...
aws_iam_policy.repro: Creation complete after 0s [id=arn:aws:iam::012345678901:policy/empty_policy_apply_repro]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
  1. Replace the policy attribute with the empty document. apply will fail (MalformedPolicyDocument: Syntax errors in policy), and in the console the original policy content persists. This is the step where the state was corrupted previously.
Show
$ terraform apply -auto-approve
data.aws_iam_policy_document.empty: Reading...
data.aws_iam_policy_document.not_empty: Reading...
data.aws_iam_policy_document.empty: Read complete after 0s [id=1132004489]
data.aws_iam_policy_document.not_empty: Read complete after 0s [id=2969320202]
aws_iam_policy.repro: Refreshing state... [id=arn:aws:iam::012345678901:policy/empty_policy_apply_repro]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_iam_policy.repro will be updated in-place
  ~ resource "aws_iam_policy" "repro" {
        id        = "arn:aws:iam::012345678901:policy/empty_policy_apply_repro"
        name      = "empty_policy_apply_repro"
      ~ policy    = jsonencode(
          ~ {
              - Statement = [
                  - {
                      - Action   = "sts:GetCallerIdentity"
                      - Effect   = "Allow"
                      - Resource = "*"
                      - Sid      = ""
                    },
                ] -> null
                # (1 unchanged element hidden)
            }
        )
        tags      = {}
        # (4 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.
aws_iam_policy.repro: Modifying... [id=arn:aws:iam::012345678901:policy/empty_policy_apply_repro]

│ Error: error updating IAM policy arn:aws:iam::012345678901:policy/empty_policy_apply_repro: MalformedPolicyDocument: Syntax errors in policy.
│       status code: 400, request id: 53d51e79-915d-4486-b4f1-11e8cb367b2c

│   with aws_iam_policy.repro,
│   on main.tf line 22, in resource "aws_iam_policy" "repro":
│   22: resource "aws_iam_policy" "repro" {


$ terraform state show aws_iam_policy.repro
# aws_iam_policy.repro:
resource "aws_iam_policy" "repro" {
    arn       = "arn:aws:iam::012345678901:policy/empty_policy_apply_repro"
    id        = "arn:aws:iam::012345678901:policy/empty_policy_apply_repro"
    name      = "empty_policy_apply_repro"
    path      = "/"
    policy    = jsonencode(
        {
            Version = "2012-10-17"
        }
    )
    policy_id = "ANPA2SZQJ22F2OQETWA4I"
    tags      = {}
    tags_all  = {}
}
  1. Revert to the original or new valid policy content. Previously this would have resulted in Error: while setting policy (), but now empty statements are handled gracefully and the apply can proceed.
Show

With the original content:

$ terraform apply -auto-approve
data.aws_iam_policy_document.empty: Reading...
data.aws_iam_policy_document.not_empty: Reading...
data.aws_iam_policy_document.empty: Read complete after 0s [id=1132004489]
data.aws_iam_policy_document.not_empty: Read complete after 0s [id=2969320202]
aws_iam_policy.repro: Refreshing state... [id=arn:aws:iam::012345678901:policy/empty_policy_apply_repro]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

With new content:

$ terraform apply -auto-approve
data.aws_iam_policy_document.empty: Reading...
data.aws_iam_policy_document.not_empty: Reading...
data.aws_iam_policy_document.empty: Read complete after 0s [id=1132004489]
data.aws_iam_policy_document.not_empty: Read complete after 0s [id=924433171]
aws_iam_policy.repro: Refreshing state... [id=arn:aws:iam::012345678901:policy/empty_policy_apply_repro]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_iam_policy.repro will be updated in-place
  ~ resource "aws_iam_policy" "repro" {
        id        = "arn:aws:iam::012345678901:policy/empty_policy_apply_repro"
        name      = "empty_policy_apply_repro"
      ~ policy    = jsonencode(
          ~ {
              ~ Statement = [
                  ~ {
                      ~ Action   = "sts:GetCallerIdentity" -> "sts:Get*"
                        # (3 unchanged elements hidden)
                    },
                ]
                # (1 unchanged element hidden)
            }
        )
        tags      = {}
        # (4 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.
aws_iam_policy.repro: Modifying... [id=arn:aws:iam::012345678901:policy/empty_policy_apply_repro]
aws_iam_policy.repro: Modifications complete after 0s [id=arn:aws:iam::012345678901:policy/empty_policy_apply_repro]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

Additional Notes

Here is the same attempt at step 3 using v4.22.0 of the provider. The setting policy error is reproduced as expected.

Show
$ terraform apply -auto-approve
data.aws_iam_policy_document.empty: Reading...
data.aws_iam_policy_document.not_empty: Reading...
data.aws_iam_policy_document.empty: Read complete after 0s [id=561002259]
data.aws_iam_policy_document.not_empty: Read complete after 0s [id=2969320202]
aws_iam_policy.repro: Refreshing state... [id=arn:aws:iam::012345678901:policy/empty_policy_apply_repro]

│ Error: while setting policy (), encountered: Error parsing policy: Unknown error parsing statement

│   with aws_iam_policy.repro,
│   on main.tf line 22, in resource "aws_iam_policy" "repro":
│   22: resource "aws_iam_policy" "repro" {

In this situation, an upgrade of the provider (rm .terraform.lock.hcl, terraform init, terraform apply) allows the apply to proceed successfully.

@jar-b jar-b added the waiting-response Maintainers are waiting on response from community or contributor. label Oct 28, 2022
@jar-b
Copy link
Member

jar-b commented Nov 18, 2022

Closing given no further response to reproduction. Resolved by #23060.

@jar-b jar-b closed this as completed Nov 18, 2022
@github-actions github-actions bot removed the waiting-response Maintainers are waiting on response from community or contributor. label Nov 18, 2022
@github-actions
Copy link

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Addresses a defect in current functionality. service/iam Issues and PRs that pertain to the iam service.
Projects
None yet
Development

No branches or pull requests

7 participants