AWS Terraform: How to give `kms:Decrypt` to an instance profile that can read from the SSM param store?

114 Views Asked by At

I am attempting to create an instance profile that allows EC2 instances to perform retrieval of SSM Param Store keys as well as decrypt them via their associated KMS key.

I have created the profile so far with only SSM Parameter read permissions, but not permission to decrypt. See below:

main.tf

# main.tf

provider "aws" {
  region = var.aws_config.region
}

# Create an IAM role
resource "aws_iam_role" "ssm_read_role" {
  name = var.iam_ssm_read_config.role_name
  assume_role_policy = file("iam/ec2_ssm_read_role_assume_policy.json")
}

# Attach AmazonSSMReadOnlyAccess policy to the IAM role
resource "aws_iam_role_policy_attachment" "ssm_policy_attachment" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess"
  role       = aws_iam_role.ssm_read_role.name
}

# Create a EC2 profile of for assuming the role
resource "aws_iam_instance_profile" "ssm_read_profile" {
  name = var.iam_ssm_read_config.profile_name
  role = aws_iam_role.ssm_read_role.name
}

output "iam_role_arn" {
  value = aws_iam_role.ssm_read_role.arn
}

output "iam_role_name" {
  value = aws_iam_role.ssm_read_role.name
}

output "iam_profile_name" {
  value = aws_iam_instance_profile.ssm_read_profile.name
}

iam/ec2_ssm_read_role_assume_policy.json


{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Principal": {
      "Service": "ec2.amazonaws.com"
    }
  }
}

Now I am attempting to use a python client to generate a configuration file using the param store, and I get this error:

botocore.exceptions.ClientError: An error occurred (AccessDeniedException) when calling the GetParameters operation: User: arn:aws:sts::983867311419:assumed-role/ssm_read_role/i-095049df3e5cs1947 is not authorized to perform: kms:Decrypt on resource: arn:aws:kms:us-west-1:983867311419:key/f460e94d-5655-4297-89ae-feha7s81jar8 because no identity-based policy allows the kms:Decrypt action (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException; Request ID: a25d9846-448a-422e-bdb6-5f12af368790; Proxy: null)

It seems I am missing the ability to decrypt with this profile. I have attempted adding it to the policy statement but receive errors because it is not an STS policy type. I also attempted creating another aws_iam_role_policy_attachment using an isolated custom policy for kms:Decrypt but this failed with:

│ Error: Unsupported attribute
│
│   on main.tf line 44, in resource "aws_iam_role_policy_attachment" "kms_decrypt_policy_attachment":
│   44:   policy_arn = aws_iam_role_policy.kms_decrypt_policy.arn
│
│ This object has no argument, nested block, or exported attribute named "arn".

What's the correct method to allow an instance profile to both retrieve and decrypt from the param store?

1

There are 1 best solutions below

0
Paolo On BEST ANSWER

The managed policy that you are using does not allow the kms:Decrypt action. To fix this, you can add an inline policy to your role:

resource "aws_iam_role" "ssm_read_role" {
  name = var.iam_ssm_read_config.role_name
  assume_role_policy = file("iam/ec2_ssm_read_role_assume_policy.json")
  inline_policy {
    name = "kms_decrypt_policy"

    policy = jsonencode({
      Version = "2012-10-17"
      Statement = [
        {
          Action   = ["kms:Decrypt"]
          Effect   = "Allow"
          Resource = "*"
        },
      ]
    })
  }
}