Home > Back-end >  Create parameterized resource policy on terraform
Create parameterized resource policy on terraform

Time:01-13

I want to create a resource policy for a Secrets Manager secret.

I am following the official example on the docs

resource "aws_secretsmanager_secret_policy" "this" {
  count      = var.create_resource_policy ? 1 : 0
  secret_arn = aws_secretsmanager_secret.mysecret.arn

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "EnableAnotherAWSAccountToReadTheSecret",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "*"
    }
  ]
}
POLICY
}

Is there a way to pass the following as variables in the policy document things as the principal(s), the action the resources etc?

I want to be able to pass those things as terraform variables.

CodePudding user response:

Yes, you can use the built-in functions in terraform for that with interpolation syntax. For example, if you had a data source to get the account ID, you could do the following:

data "aws_caller_identity" "current" {}

resource "aws_secretsmanager_secret_policy" "this" {
  count      = var.create_resource_policy ? 1 : 0
  secret_arn = aws_secretsmanager_secret.mysecret.arn

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "EnableAnotherAWSAccountToReadTheSecret",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::${data.aws_caller_identity.current.id}:root"
      },
      "Action": "secretsmanager:GetSecretValue",
      "Resource": "*"
    }
  ]
}
POLICY
}

You could then do the same for any other property you want/need. However, I find it easier to use the built-in data source [1] for creating policies. So for example, the policy you have could be written in the following way:

data "aws_iam_policy_document" "secrets_manager_policy" {
  statement {
    sid    = "EnableAnotherAWSAccountToReadTheSecret"
    effect = "Allow"
    principals {
      identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.id}:root"]
      type        = "AWS"
    }
    actions = [
      "secretsmanager:GetSecretValue"
    ]
    resources = ["*"]
  }
}

You could then tell actions argument to use a variable which would most preferably be a list(string) which would list all the actions necessary:

data "aws_iam_policy_document" "secrets_manager_policy" {
  statement {
    sid = "EnableAnotherAWSAccountToReadTheSecret"
    effect = "Allow"
    principals {
      identifiers = "arn:aws:iam::${data.aws_caller_identity.current.id}:root"
      type = "AWS"
    }
    actions = var.secrets_actions
    resources = [ "*" ]
  }
}

Then, you would only have to reference the output of the data source in the original resource:

resource "aws_secretsmanager_secret_policy" "this" {
  count      = var.create_resource_policy ? 1 : 0
  secret_arn = aws_secretsmanager_secret.mysecret.arn

  policy = data.aws_iam_policy_document.secrets_manager_policy.json
}

[1] https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document

  • Related