πŸ‘‰ AWS Debug Games (Beta) - Prove your AWS expertise by solving tricky challenges.

πŸ‘‰ AWS Debug Games - Prove your AWS expertise.

Defining IAM Policies with Terraform safely

Andreas Wittig – 31 Mar 2021

Are you still defining IAM policies using heredoc syntax (<<EOF ... EOF) or jsonencode()? You can do better! As a result, terraform validate can tell you about typos before you apply them, and you get better auto-complete support from your IDE. Read on to learn how to define IAM policies in Terraform safely.

Defining IAM Policies with Terraform

When looking at Terraform code I still see the following two ways to define IAM policies:


Looking for a new challenge?

  • DEMICON

    Cloud Operations Lead

    DEMICON • AWS Advanced Consulting Partner • Remote (Europe)
    service-delivery-management hiring devops platform

resource "aws_iam_policy" "inline" {
name = "tf-inline"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Effect": "Allow",
"Resource": "${aws_s3_bucket.example.arn}/*"
}
]
}
EOF
}

The second approach looks like this:

resource "aws_iam_policy" "jsonencode" {
name = "tf-jsonencode"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"s3:GetObject",
"s3:PutObject"
]
Resource = [
"${aws_s3_bucket.example.arn}/*"
]
}
]
})
}

The problem with both approaches: If your policy is malformed, you have to terraform apply before you realize the mistake. Besides that, your IDE’s auto-complete can not help you much when using those approaches.

How can we do better? The following video demonstrates using the data source aws_iam_policy_document. This way, Terraform can validate your IAM policy (at least from a structural perspective), and your IDE can do a much better job of increasing your productivity.

resource "aws_iam_policy" "policydocument" {
name = "tf-policydocument"
policy = data.aws_iam_policy_document.example.json
}

data "aws_iam_policy_document" "example" {
statement {
effect = "Allow"
actions = [
"s3:ListBucket"
]
resources = [
aws_s3_bucket.example.arn
]
}
statement {
effect = "Allow"
actions = [
"s3:GetObject",
"s3:PutObject"
]
resources = [
"${aws_s3_bucket.example.arn}/*"
]
}
}

Become a cloudonaut supporter

Andreas Wittig

Andreas Wittig ( Email Twitter LinkedIn Mastodon )

We launched the cloudonaut blog in 2015. Since then, we have published 365 articles, 68 podcast episodes, and 68 videos. It's all free and means a lot of work in our spare time. We enjoy sharing our AWS knowledge with you.

Please support us

Have you learned something new by reading, listening, or watching our content? With your help, we can spend enough time to keep publishing great content in the future. Learn more

$
Amount must be a multriply of 5. E.g, 5, 10, 15.

Thanks to Alan Leech, Alex DeBrie, Christopher Hipwell, Jason Yorty, Jeff Finley, jhoadley, Johannes Konings, John Culkin, Jonathan Deamer, Juraj Martinka, Ken Snyder, Markus Ellers, Oriol Rodriguez, Ross Mohan, sam onaga, Satyendra Sharma, Simon Devlin, Todd Valentine, Victor Grenu, and all anonymous supporters for your help! We also want to thank all supporters who purchased a cloudonaut t-shirt.