
In previous chapters, you learned the foundational steps of constructing a serverless application using infrastructure as code (IaC). In this appendix, you learn how to use EventBridge as part of your serverless applications and use event-driven architecture (EDA) primitives.
In many scenarios, developers design applications to respond to events. Amazon EventBridge Event Bus is a serverless event bus that helps you receive, filter, transform, route, and deliver events to over 200 targets. In this chapter you learn how to route different event types to a variety of AWS targets.
Documentation for AWS Health states the following
You can use Amazon EventBridge to detect and react to AWS Health events. Then, based on rules that you create, EventBridge invokes one or more target actions when an event matches the values that you specify in a rule.
AWS delivers events from services to the default EventBridge bus. You can add a routing rule for that bus looking for events originating from the aws.health source and configure sending those events to different AWS targets.
Using the same directory structure as in previous chapters.
├── main.tf
├── modules
│ └── eb
│ └── eb-aws-health
│ ├── cloudwatch-logs-target.tf
│ ├── main.tf
│ ├── outputs.tf
│ ├── sns-target.tf
│ └── versions.tf
├── outputs.tf
├── providers.tf
├── variables.tf
└── versions.tf
In your ./main.tf file add the new module reference:
module "eb_rule_aws_health" {
source = "./modules/eb/eb-aws-health"
providers = {
aws = aws.use1
}
}
Configure the EventBridge resources in the ./modules/eb/eb-aws-health/main.tf file.
# Captures events sent to the default eventbridge bus from AWS Health
resource "aws_cloudwatch_event_rule" "eb_rule_aws_health" {
name = "CaptureAWSHealthEvents"
description = "AWS Health Events"
event_pattern = jsonencode({
source = [
"aws.health"
]
})
}
# Define a target for event delivery
resource "aws_cloudwatch_event_target" "send-to-cw-logs" {
rule = aws_cloudwatch_event_rule.eb_rule_aws_health.name
arn = aws_cloudwatch_log_group.awshealth.arn
}
The source property in the above snippet enables the rule to only match events coming from AWS Health, after which events are sent to CloudWatch Logs.
{
"source": ["aws.health"]
}
For event delivery to work, you need to define IAM policies. You also need to define the log retention perior for the target CloudWatch Logs group.
resource "aws_cloudwatch_log_group" "awshealth" {
name = "/aws/events/health/logs"
retention_in_days = 7
}
data "aws_iam_policy_document" "awshealth" {
statement {
effect = "Allow"
actions = [
"logs:CreateLogStream"
]
resources = [
"${aws_cloudwatch_log_group.awshealth.arn}:*"
]
principals {
type = "Service"
identifiers = [
"events.amazonaws.com",
"delivery.logs.amazonaws.com"
]
}
}
statement {
effect = "Allow"
actions = [
"logs:PutLogEvents"
]
resources = [
"${aws_cloudwatch_log_group.awshealth.arn}:*:*"
]
principals {
type = "Service"
identifiers = [
"events.amazonaws.com",
"delivery.logs.amazonaws.com"
]
}
condition {
test = "ArnEquals"
values = [aws_cloudwatch_event_rule.eb_rule_aws_health.arn]
variable = "aws:SourceArn"
}
}
}
resource "aws_cloudwatch_log_resource_policy" "awshealth" {
policy_document = data.aws_iam_policy_document.awshealth.json
policy_name = "awshealth-eb-log-publishing-policy"
}
Run terraform apply to apply the updates. With this IaC configuration applied, you see AWS Health events in your CloudWatch Logs. In addition to sending events to CloudWatch, you can also deliver them via email by using Amazon SNS, or start a serverless workflow by invoking a Lambda function or executing a Step Functions state machine.
The following JSON snippet illustrates a sample AWS Health event received through EventBridge.
{
"version": "0",
"id": "34afc3ea-e5dd-e2fa-cdf6-e5d1781dd41b",
"detail-type": "AWS Health Event",
"source": "aws.health",
"account": "123456789001",
"time": "2024-06-04T07:20:41Z",
"region": "us-west-2",
"resources": [
"prodSearch01-infra"
],
"detail": {
"eventArn": "arn:aws:health:us-west-2::event/ES/**REDACTED**",
"service": "ES",
"eventTypeCode": "AWS_ES_SERVICE_SOFTWARE_UPDATE_AVAILABLE",
"eventTypeCategory": "accountNotification",
"eventScopeCode": "ACCOUNT_SPECIFIC",
"communicationId": "**REDACTED**",
"startTime": "Tue, 4 Jun 2024 07:16:05 GMT",
"lastUpdatedTime": "Tue, 4 Jun 2024 07:20:01 GMT",
"statusCode": "open",
"eventRegion": "us-west-2",
"eventDescription": [
{
"language": "en_US",
"latestDescription": "A new service software update OpenSearch_2_11_R20240502-P2 is available **REDACTED**"
}
],
"affectedEntities": [
{
"entityValue": "prodSearch01-infra",
"status": "IMPAIRED",
"lastUpdatedTime": "Tue, 4 Jun 2024 07:20:01 GMT"
}
],
"affectedAccount": "123456789001",
"page": "1",
"totalPages": "1"
}
}
Now that you understand the format of the event, you can add custom filtering and routing in your EventBridge Rules to route them to the correct target. For example, you want to monitor for Amazon Relational Database Service (RDS) deprecation notifications and send emails to the DBA team so that they can plan and schedule the major version upgrades. You can use Planned lifecycle events for AWS Health to route important events to targets.
The following code snippets shows how to implement custom filtering and routing described above.
Configure the SNS topic:
resource "aws_sns_topic" "notify_dbas" {
name = "notify-dba-team"
}
resource "aws_sns_topic_policy" "default" {
arn = aws_sns_topic.notify_dbas.arn
policy = data.aws_iam_policy_document.sns_topic_policy.json
}
data "aws_iam_policy_document" "sns_topic_policy" {
statement {
effect = "Allow"
actions = ["SNS:Publish"]
principals {
type = "Service"
identifiers = ["events.amazonaws.com"]
}
resources = [aws_sns_topic.notify_dbas.arn]
}
}
Then create an EventBridge target and rule resources.
# Define SNS topic created above as EventBridge event target
resource "aws_cloudwatch_event_target" "sns_notify_dba" {
rule = aws_cloudwatch_event_rule.eb_rule_aws_health_rds_events.name
target_id = "NotifyDBAs"
arn = aws_sns_topic.notify_dbas.arn
}
# Capture events sent to the default EventBridge bus
# from AWS Health for RDS updates, and notify the DBA team
# over SNS.
resource "aws_cloudwatch_event_rule" "eb_rule_aws_health_rds_events" {
name = "CaptureAWSHealthEvents_AWS_RDS_PLANNED_LIFECYCLE_EVENT"
description = "AWS RDS Lifecycle events"
event_pattern = jsonencode({
source = [
"aws.health"
],
detail = {
eventTypeCode = ["AWS_RDS_PLANNED_LIFECYCLE_EVENT"]
}
})
}
Now the DBA team is notified via SNS for important RDS events, such as major version upgrades or deprecation notices.
This module shows how to use Terraform to capture events from AWS Health and route them to different targets. Using this pattern you can drive important events to different targets, and respond to events in a meaningful way. This technique can be applied for operational events, such as alerts or tickets, as well as business use cases, such as order-placed or shipment-delivered.
Using the patterns described above you can build your own event-driven architectures to cover a variety of operational and business use cases.
Learn more about using EventBridge by following the Building event-driven architectures on AWS workshop.