4
votes

I have an existing IAM policy attached to a role. Each time a new secret is created in the Secrets Manager, I need to append the new ARN to the policy. Can this be done with Terraform? I've managed to import the policy into the terraform.state file, but I don't know how to: 1) Append a new ARN inside the "Resources" list 2) Push the change to AWS

This is how the policy looks now:

{
"Version": "2012-10-17",
"Statement": [
    {
        "Effect": "Allow",
        "Action": "secretsmanager:GetSecretValue",
        "Resource": [
            "SECRET_ARN_1",
            "SECRET_ARN_2",
            "SECRET_ARN_3"
        ]
    },
    {
        "Effect": "Allow",
        "Action": "kms:Decrypt",
        "Resource": "KMS_ARN"
    }
]

}

And this is how I need it to look:

{
"Version": "2012-10-17",
"Statement": [
    {
        "Effect": "Allow",
        "Action": "secretsmanager:GetSecretValue",
        "Resource": [
            "SECRET_ARN_1",
            "SECRET_ARN_2",
            "SECRET_ARN_3",
            "MY_BRAND_NEW_SECRET_ARN"
        ]
    },
    {
        "Effect": "Allow",
        "Action": "kms:Decrypt",
        "Resource": "KMS_ARN"
    }
]

}

The following import is working by importing the existing policy to the object aws_iam_policy.mysimplepolicy, but I don't know how to proceed from here.

terraform import aws_iam_policy.mysimplepolicy <MY_POLICY_ARN>
2

2 Answers

3
votes

It sounds like you've already figured out how to import the policy in to your state. Now you need to define the resource in your Terraform code so it matches the policy.

First, define variables for the ARNs:

variable "secret_arns" {
    description = "A list of secret manager ARNs that the IAM policy should permit access to."
    type        = list(string)
}

variable "kms_key_arns" {
    description = "A list of KMS Key ARNs that the IAM policy should permit access to."
    type        = list(string)
}

Next, define the policy document as a data source, using the variables:

data "aws_iam_policy_document" "secret_access" {
    statement {
        sid       = "SecretsAccess"
        actions   = ["secretsmanager:GetSecretValue"]
        resources = var.secret_arns
        effect    = "Allow"
    }
    statement {
        sid       = "KMSAccess"
        actions   = "kms:Decrypt"
        resources = var.kms_key_arns
        effect    = "Allow"
    }
}

Now create a policy using the data source:

resource "aws_iam_policy" "mysimplepolicy" {
  name   = "MySimplePolicy"  # Make sure this has the name you want
  policy = data.aws_iam_policy_document.secret_access.json
}

Finally, when you call the code, pass in the ARNs in your variables using whatever method you prefer. It could be from a terraform.tfvars file or on the command line using the -var syntax or as output from another Terraform module that creates the secrets. For example:

terraform apply -var='secret_arns=["arn1", "arn2", <etc>]' -var='kms_key_arns=["key-arn1", "key-arn2"]'

Every time you append a new item to one of the variables and run terraform apply, Terraform will update the policy accordingly.

2
votes

Another, possibly easier, option would be to use tag based authorization. That is to say, modify the policy to only grant access to secrets with a specific tag and then when you create the secret add that tag. There are also example docs for doing this.