Use terrform to update a KMS Key Policy

16,424

Solution 1

The answer from BMW is right if the Key Policy disables the use of IAM roles, however, if the KMS Key Policy has been set up to enable IAM policies then you might not need to update it.

The docs for using key policies explains that you must have a Key Policy, but you can optionally also use IAM policies to control access.

If the KMS Key Policy contains this statement, then IAM Policies are enabled, and you can proceed with creating IAM Policies to solve the issue; you don't need to worry about updating the Key Policy.

{
  "Sid": "Enable IAM User Permissions",
  "Effect": "Allow",
  "Principal": {"AWS": "arn:aws:iam::111122223333:root"},
  "Action": "kms:*",
  "Resource": "*"
}

In Terraform you could create an IAM Policy, and attach it to that temp role.

The following assumes you have already got the code in Terraform for the Temp IAM Role, which I've referred to here as temp_role_made_earlier

Create an IAM Policy document (recommended method, nicer than importing json and less messy that using templates)

data "aws_iam_policy_document" "kms_use" {
  statement {
    sid = "Allow KMS Use"
    effect = "Allow"
    actions = [
      "kms:Encrypt",
      "kms:Decrypt",
      "kms:ReEncrypt*",
      "kms:GenerateDataKey*",
      "kms:DescribeKey",
    ]
    resources = [
      "<arn of the key goes here>"
    ]
  }
}

Create an IAM Policy from that document

resource "aws_iam_policy" "kms_use" {
  name        = "kmsuse"
  description = "Policy to allow use of KMS Key"
  policy      = "${data.aws_iam_policy_document.kms_use.json}"
}

Attach it to the role

resource "aws_iam_role_policy_attachment" "temp" {
  role       = "${aws_iam_role.temp_role_made_earlier.name}"
  policy_arn = "${aws_iam_policy.kms_use.arn}"
}

NOTE

  • aws_iam_role_policy_attachment uses the name attribute for the role, not the arn.
  • You can attach as many policies as you like to roles
  • If you don't know the Key's arn but you know the KMS key's alias, you can look up the arn using an aws_kms_key data source which will let you fetch the arn without terraform taking over control of the Key resource. It can also be helpful to validate that the key exists.

Solution 2

If the kms key is exist and not controlled by terraform, you need to import this resource first.

First, make sure you have these codes ready

resource "aws_iam_role" "example" {
  name = "example"
  assume_role_policy = "<redacted>"
}

resource "aws_kms_key" "example" {
  description = "example"
  deletion_window_in_days = 10

  policy = "${file("kms-policy.json")}"
}

Then run terraform import to import this resource.

$ terraform import aws_kms_key.example arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab

After that, the kms key can be managed by terraform, you are fine to update its iam role now with terraform plan/apply

Share:
16,424
SnazzyBootMan
Author by

SnazzyBootMan

Updated on June 23, 2022

Comments

  • SnazzyBootMan
    SnazzyBootMan almost 2 years

    Does anyone know how I would get Terraform to UPDATE an existing KMS Key policy?

    I already have the KMS Key(s) created but I have a temporary IAM role that needs to use an existing KMS key. I would like to be able to add this "new" IAM role to the existing KMS Key policy. I can see that this is possible using the AWS console but I can't see how do do this in Terraform.

    I would imagine that this is also possible using the AWS CLI tools but I haven't investigated that as I am building an environment in Terraform and would like to keep it all in the one place.

    I should point out that the current KMS key is used to encrypt S3 uploads and downloads and various IAM users and roles already have access to the current key so creating a new key would just invert the issue for those already accessing the buckets.