Use variables inside IAM policy

1,548 views
Skip to first unread message

Andrew Langhorn

unread,
Nov 15, 2016, 8:21:39 AM11/15/16
to terrafo...@googlegroups.com
Hi,

Is it possible to use either (preferably, both) an interpolated value or a value derived from a Terraform output inside an AWS IAM policy?

I'd like to use the same policy for multiple things, differentiated on both the account number (which is used by our CloudTrail policy) and also on environment (which we specify using var.environment).

Any examples you have would be greatly appreciated, too.

Thanks,

Andrew







David Adams

unread,
Nov 15, 2016, 9:47:52 AM11/15/16
to terrafo...@googlegroups.com
It's absolutely possible. eg, I have a module I include in all my projects that takes a region code and a codename for an account, and makes available a bunch of metadata like subnet IDs, VPC IDs, security group IDs, the account ID, etc. (You can also use the aws_caller_identity data source these days to get the account ID, but that gives you the account ID your credentials are associated with, which may or may not be what you actually want: https://www.terraform.io/docs/providers/aws/d/caller_identity.html) So here's a working snippet in situ with the relevant requirements:

    variable "env" { default = "prod" }

    module "metadata" {
      source = "../modules/aws-metadata"
      account = "main"
      region = "pdx"
      env = "${var.env}"
    }

    provider "aws" {
      region = "${module.metadata.region_name}"
      allowed_account_ids = ["${module.metadata.account_id}"]
      assume_role { role_arn = "${module.metadata.ops_role_arn}" }
    }

    data "aws_iam_policy_document" "kinesis" {
      statement {
        resources = ["arn:aws:kinesis:${module.metadata.region_name}:${module.metadata.account_id}:stream/myapp-${var.env}-*"]
        actions = [
          "kinesis:AddTagsToStream",
          "kinesis:DescribeStream",
          "kinesis:PutRecord",
          "kinesis:PutRecords",
        ]
      }
    }




--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
 
GitHub Issues: https://github.com/hashicorp/terraform/issues
IRC: #terraform-tool on Freenode
---
You received this message because you are subscribed to the Google Groups "Terraform" group.
To unsubscribe from this group and stop receiving emails from it, send an email to terraform-tool+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/terraform-tool/CAEpa1D%2BEM6kqAm%2BWR9LBtX-8VOqz5o9y6mt%3DCy2s7d%3Dd-LJ0Lg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Andrew Langhorn

unread,
Nov 15, 2016, 10:41:54 AM11/15/16
to terrafo...@googlegroups.com
Hi David,

Hmm; that's exactly what I'm trying to do, except using a policy written to a file and dragged in using the file function.

I'm fairly certain I've had variables inside IAM policies working inside files before now...

Andrew


For more options, visit https://groups.google.com/d/optout.



--

Andrew Langhorn
Senior Site Reliability Engineer
Emailandrew....@thoughtworks.com
Telephone+44 7733 339809
ThoughtWorks

David Adams

unread,
Nov 15, 2016, 10:49:38 AM11/15/16
to terrafo...@googlegroups.com
Oh, I'm guessing you might have to resort to using the template_file datasource, something like:

    data "template_file" "policy" {
      template = "${file("policy.tpl")}"
      vars {
        region = "${module.metadata.region_name}"
        account_id = "${module.metadata.account_id}"
        env = "${var.env}"
      }
    }

And policy.tpl looking like:

    {
      "Resource": "arn:aws:kinesis:${region}:${account_id}:stream/myapp-${env}-*"
      ... etc

But you can't pull in the interpolations for "var.env" etc directly, you have to pass them thru the vars {} block to give them a simple name.

--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
 
GitHub Issues: https://github.com/hashicorp/terraform/issues
IRC: #terraform-tool on Freenode
---
You received this message because you are subscribed to the Google Groups "Terraform" group.
To unsubscribe from this group and stop receiving emails from it, send an email to terraform-tool+unsubscribe@googlegroups.com.

Andrew Langhorn

unread,
Nov 15, 2016, 11:02:41 AM11/15/16
to terrafo...@googlegroups.com
Yeah, it's increasingly looking that way.
Thankfully, not a difficult re-factor at this stage.

Will give that a go.

cheers

Andrew Langhorn

unread,
Nov 15, 2016, 11:41:36 AM11/15/16
to Andrew Langhorn, terrafo...@googlegroups.com
Hi,

So, I now have this:

data "template_file" "foo" {
  template = "${file("/path/to/file.tpl")}"
  vars {
    environment = "${var.environment}"
  }
}

and in /path/to/file.tpl, I have:

...
"Resource": [
  "arn:aws:s3:::foo-bar-${environment}-data",
  "arn:aws:s3:::foo-bar-${environment}-data/*"
]
...

But now it seems that Terraform is refusing to interpolate environment, since the policy it tries to apply contains a literal reference to ${environment}. I thought that might be down to escaping, so I prefixed with $$ instead of $, but that appears not to be working.

Any idea what I'm missing? Looks like escaping might be the problem here, but I can't quite see what it is that's causing me the pain.

Thanks,

Andrew Langhorn

unread,
Nov 15, 2016, 12:15:54 PM11/15/16
to Andrew Langhorn, terrafo...@googlegroups.com
So, I think I fixed this in the end: the bit I was missing was not reading the rendered output as the input to the policy argument on the S3 bucket resource.

Thanks!
Reply all
Reply to author
Forward
0 new messages