
Ostensibly this is easy. Set an event rule target to a log group and it Just Works ™.
I suspect that’s probably the case in the AWS UI, but with infra as code there’s a missing piece: cloudwatch logs resource policies. There has to be a policy in place that allows events to delivery logs. In the UI, I suspect AWS does this for you, but without the UI, there is a bit of extra code.
data "aws_iam_policy_document" "cloudwatch-logs-from-events" {
statement {
effect = "Allow"
actions = [
"logs:CreateLogStream",
"logs:PutLogEvents",
]
resources = [
"arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:/aws/events/*:*"
]
principals {
type = "Service"
identifiers = [
"events.amazonaws.com",
"delivery.logs.amazonaws.com", // unclear if this is necessary, but every example I could find has it
]
}
}
}
resource "aws_cloudwatch_log_resource_policy" "cloudwatch-logs-from-events" {
policy_document = data.aws_iam_policy_document.cloudwatch-logs-from-events.json
policy_name = "${var.app}-${var.env}-cloudwatch-logs-from-events"
}
Note that I attemped confused deputy protection in the above via an aws:SourceAccount condition and it did not work.
This allows events to send to /aws/events/* log groups.
With this in place connecting a rule target to a cloudwatch logs will work.
resource "aws_cloudwatch_log_group" "ses-events" {
name = "/aws/events/example"
retention_in_days = 14
}
resource "aws_cloudwatch_event_rule" "example" {
name = "example"
event_pattern = jsonencode({
// CHANGEME
})
}
resource "aws_cloudwatch_event_target" "ses-events-cloudwatch" {
target_id = "example"
rule = aws_cloudwatch_event_rule.example.name
arn = aws_cloudwatch_log_group.example.arn
}