Problem
An aws_iam_policy_document data source with no statement blocks produces a document that the aws_iam_policy resource cannot parse, resulting in an error during a terraform plan or terraform apply.
Cause
This issue occurs after a sequence of changes in the Terraform state. First, a configuration with a valid statement is applied and saved to the state file.
For example, this initial configuration is valid.
data "aws_iam_policy_document" "maybe_empty" {
statement {
actions = ["ssm:SendCommand"]
resources = ["*"]
}
}
resource "aws_iam_policy" "example" {
name = "example"
policy = data.aws_iam_policy_document.maybe_empty.json
}Later, the statement block is removed or commented out from the configuration.
data "aws_iam_policy_document" "maybe_empty" {
## statement {
## actions = ["ssm:SendCommand"]
## resources = ["*"]
## }
}
resource "aws_iam_policy" "example" {
name = "example"
policy = data.aws_iam_policy_document.maybe_empty.json
}With an empty statement, the data source produces a JSON document where the Statement attribute is null. You can verify this by inspecting the state.
$ terraform state show data.aws_iam_policy_document.maybe_empty
The resulting policy document appears as follows.
{
"Version": "2012-10-17",
"Statement": null
}On the next terraform plan, Terraform attempts to read the existing policy from AWS to compare it with the new configuration. The AWS API returns an error because it cannot parse a policy document where the Statement is null.
This results in the following error.
Error: while setting policy (), encountered: Error parsing 1 policy: Unknown error parsing statement
Solution
To resolve this issue, you must remove the invalid policy from the Terraform state, ensure the configuration contains at least one valid statement, and re-import the resources.
Procedure
- Connect to the remote backend if you are using one.
-
Initialize the working directory. This allows Terraform to copy the remote state locally.
$ terraform init
-
Remove the
aws_iam_policyresource from the Terraform state file. Replace$policy_namewith the name of your policy resource.$ terraform state rm aws_iam_policy.$policy_name
-
Remove the
aws_iam_policy_documentdata source from the Terraform state file. Replace$policy_namewith the name of your data source.$ terraform state rm data.aws_iam_policy_document.$policy_name
- Update your Terraform configuration to ensure the
aws_iam_policy_documentdata source contains at least one validstatementblock. -
Import both resources back into the state file.
$ terraform import aws_iam_policy.$policy_name <POLICY_ARN> $ terraform import data.aws_iam_policy_document.$policy_name <POLICY_ARN>
-
Run
terraform planto confirm that the state matches your configuration, then runterraform apply.$ terraform plan
$ terraform apply