Reputation: 1223
I am getting the exactly same error as described in https://aws.amazon.com/premiumsupport/knowledge-center/cloudwatch-receive-sns-for-alarm-trigger/. The error I get is null (Service: AWSKMS; Status Code: 400; Error Code: AccessDeniedException;)
.
All the online resources I read point out that the CMK must have these two permissions for the AWS CloudWatch alarms: "kms:Decrypt","kms:GenerateDataKey"
. What I did (in terraform) was:
resource "aws_iam_role" "cloudwatch-alarm-role" {
name = var.cloudwatch_alarm_role_name
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "cloudwatch.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_kms_key" "mycreds" {
description = "CMK for encrypting my data"
tags = merge(
var.my_tags,
{
"Name" = "My Credentials CMK"
},
)
}
resource "aws_kms_grant" "cloudwatch_alarm_role_grant" {
name = "cloudwatch-alarm-grant"
key_id = aws_kms_key.mycreds.key_id
grantee_principal = data.aws_iam_role.cloudwatch_alarm_role.arn
operations = ["Encrypt", "Decrypt", "GenerateDataKey"]
}
resource "aws_sns_topic" "messages" {
name = "messages-topic"
kms_master_key_id = aws_kms_key.mycreds.key_id
}
but I still get the same access denied error. What am I missing?
Upvotes: 1
Views: 1483
Reputation: 1357
We had a similar issue. Figured out that we are supposed to add a policy to the aws_kms_key resource itself, rather than add aws_kms_grant resource. The below code is what worked for us.
resource "aws_kms_key" "sns_key" {
description = "KMS key for use in SNS through CloudWatch Alarms"
policy = data.aws_iam_policy_document.sns_key_policy.json
tags = var.default_tags
}
data "aws_iam_policy_document" "sns_key_policy" {
statement {
sid = "Enable_IAM_root_permissions"
effect = "Allow"
resources = ["*"]
actions = ["kms:*"]
principals {
type = "AWS"
identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"]
}
}
statement {
sid = "Allow_CloudWatch_for_CMK"
effect = "Allow"
resources = ["*"]
actions = [
"kms:Decrypt",
"kms:GenerateDataKey*",
]
principals {
type = "Service"
identifiers = ["cloudwatch.amazonaws.com"]
}
}
}
Please note: it requires us to add a statement for access to the root user as well. Otherwise, the key would become un-deletable.
Upvotes: 2