fhcat
fhcat

Reputation: 1223

AWS CloudWatch Metric Alarm not able to notify via SNS

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:

  1. Created an IAM role with following definition:
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

}
  1. Grant the role KMS operations:
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"]
}

  1. Definition of the SNS topic:
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

Answers (1)

Technowise
Technowise

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

Related Questions