EventBus++ is a Terraform module for deploying a managed instance of Amazon’s EventBridge and associated services. The instance is configured with sane defaults and options to extend the functionality for the needs of your application.
The most minimal implementation of this module can be deployed by including the following terraform block:
module "eventbus_example" {
source = "git::ssh://[email protected]/proactiveops/eventbus?ref=main"
name = "example"
tags = {
environment = "dev"
}
}
In the example above a new EventBridge instance will be deployed with the name example-dev
.
EventBus++ makes it easy to enable debugging on a cross bus rule. When enabled on a target it logs all events to a CloudWatch Log group.
debug
is optional and it defaults to false
. When set to true
to create all the necessary resources required for debugging rules managed by EventBus++.
You can configure this feature with the following code
module "eventbus_debug" {
source = "git::ssh://[email protected]/proactiveops/eventbus?ref=main"
name = "example"
# ...
cross_bus_rules = [
{
name = "cross_bus_test_rule",
pattern = jsonencode({ "source" = ["event-source"] }),
target_arn = "arn:aws:events:us-east-1:012345678910:event-bus/target"
debug = true
}
]
tags = {
environment = "dev"
}
}
For most rules there should be a Dead Letter Queue (DLQ). EventBus++ makes it easy to configure a DLQ for a cross bus rule. The 'dlq_arn' property is optional, so if it is omitted it won't be configured.
You can configure this feature with the following code:
module "eventbus_dlq" {
source = "git::ssh://[email protected]/proactiveops/eventbus?ref=main"
name = "example"
# ...
cross_bus_rules = [
{
name = "cross_bus_test_rule",
pattern = jsonencode({ "source" = ["event-source"] }),
target_arn = "arn:aws:events:us-east-1:012345678910:event-bus/target"
dlq_arn = module.eventbus_dlq_config.dlq_arn
}
]
tags = {
environment = "dev"
}
}
EventBus++ includes a sub module for creating an encrypted SQS queue that can be used as a DLQ. This queue created by the DLQ sub module can be passed to a cross bus rule via the dlq\_arn
property in the rule config. See the DLQ submodule for details on how to use this module.
Within AWS EventBridge event routing is broken up into two parts - rules and targets. Rules specify a pattern to match events. The rule doesn’t route the event.
While it is possible to implement complex rules for matching events, this can make debugging in production more difficult. Aim for simpler rules where ever possible, your future self will thank you.
Here is an example of a simple rule which matches all deployment completed events.
resource "aws_cloudwatch_event_rule" "example_deployment_complete" {
name = "deployments-complete"
description = "Capture deployment complete events from my-service"
event_bus_name = module.eventbus_example.eventbridge.name # Needed so we listen to the correct bridge instance.
event_pattern = jsonencode({
"source" : ["my-service"],
"detail-type" : ["deployment-completed"]
})
}
Amazon’s documentation on event pattern matching provides more examples of matching rules. For full details of the configuration options for the aws_cloudwatch_event_rule
resource, refer to the terraform documentation.
The default limit of rules per event bus is 300. This can be raised by requesting a quota increase if you have a business need for a higher quota.
Once we have our rules, we need to use targets to route our events to another service.
In this example we are routing our deployment complete events to an SQS queue in the same account.
resource "aws_cloudwatch_event_target" "example_deployment_complete_to_sqs" {
rule = aws_cloudwatch_event_rule.example_deployment_complete.name
target_id = "example-deployment-complete-to-sqs"
arn = aws_sqs_queue.this.arn
event_bus_name = aws_cloudwatch_event_rule.example_deployment_complete.event_bus_name
}
You may need to configure the resource policy on the target resource before it accepts your events. Amazon provides example resource policies for common services.
For other resources or cross account routing you will need to provision an IAM role for the bridge to assume when sending the events.
If you need to route events from one EventBus++ instance to another, you can use the cross_bus_rules
variable to simplify your setup. Each map in the list will provision the rule, target and IAM role for you. Each name
property must be unique for each bus to avoid conflicts. The pattern
property is any valid event matching pattern. See rules section above for event pattern matching configuration.
module "eventbus_example" {
source = "git::ssh://[email protected]/proactiveops/eventbus?ref=main"
name = "example"
cross_bus_rules = [
{
name = "cross_bus_test_rule",
pattern = jsonencode({ "source" = ["event-source"] }),
target_arn = "arn:aws:events:us-east-1:012345678910:event-bus/target"
debug = true
},
# ...
]
tags = {
environment = "dev"
}
}
The list of supported EventBridge targets is growing all the time. If a target isn’t supported, you can use a Lambda function to invoke the API call with your event payload.
For all available configuration options for the aws_cloudwatch_event_target
resource, refer to the terraform documentation.
Both the AWS and terraform documentation provide examples of using input transformers to manipulate events before sending them to the target. This is a useful feature if you only need some of the event payload to be sent to the target.
Each EventBridge instance provisioned by EventBus++ has a resource policy attached to it that implements IAM controls, so that roles in the same account can be granted access to the bridge. Granting the events:PutEvents
action on your bridge resource is enough to allow the role access.
When sending events from another account, additional configuration is required. The allow_put_events_arns
variable allows you to specify a list of EventBridge rule ARNs that can send events to the bridge. An example of this is included below.
module "eventbus_put_events" {
source = "git::ssh://[email protected]/proactiveops/eventbus?ref=main"
name = "example"
allow_put_events_arns = [
"arn:aws:events:us-east-1:012345678910:rule/EventBus-example-dev/my-rule",
# ...
]
tags = {
environment = "dev"
}
}
If you require more complex rules, you can pass a list of data.aws_iam_policy_document.json
strings to the EventBus++ module using the bus_policy_docs
variable. An example of this is included below.
data "aws_iam_policy_document" "example_document" {
# ...
}
module "eventbus_bus_policies" {
source = "git::ssh://[email protected]/proactiveops/eventbus?ref=main"
name = "example"
bus_policy_docs = [data.aws_iam_policy_document.example_document.json]
allow_put_events_arns = [
"arn:aws:events:us-east-1:012345678910:rule/EventBus-example-dev/my-rule",
# ...
]
tags = {
environment = "dev"
}
}
The dlq sub module provisions a new SQS queue that can be used as Dead Letter Queue (DLQ). It will optionally create a new KMS key for encrypting the messages at rest.
A single DLQ can be used for more than one rule.
Add the sub module to your terraform module like so:
module "eventbus_dlq_example" {
source = "git::ssh://[email protected]/proactiveops/eventbus//modules/dlq?ref=main"
queue_name = "[sub-name]-[optional-rule-name]" # Must not exceed 60 characters as the module appends "-dlq" to the name
kms_key_id = aws_kms_key.my_key.id # omit if you want a new KMS key to be created.
tags = var.tags
}
Name | Version |
---|---|
terraform | >= 1.0 |
aws | >= 4.0, <5.0 |
Name | Version |
---|---|
aws | >= 4.0, <5.0 |
No modules.
Name | Type |
---|---|
aws_cloudwatch_event_archive.this | resource |
aws_cloudwatch_event_bus.this | resource |
aws_cloudwatch_event_bus_policy.this | resource |
aws_cloudwatch_event_rule.targets | resource |
aws_cloudwatch_event_target.targets | resource |
aws_cloudwatch_event_target.this | resource |
aws_cloudwatch_log_group.this | resource |
aws_iam_policy.events_cross_account | resource |
aws_iam_role.events_cross_account | resource |
aws_iam_role_policy_attachment.events_cross_account | resource |
aws_schemas_discoverer.this | resource |
aws_caller_identity.current | data source |
aws_cloudwatch_event_source.partner | data source |
aws_iam_policy_document.event_bus | data source |
aws_iam_policy_document.events_assume | data source |
aws_iam_policy_document.events_cross_account | data source |
aws_partition.current | data source |
aws_region.current | data source |
Name | Description | Type | Default | Required |
---|---|---|---|---|
allow_put_events_arns | List of ARNs allowed to call PutEvents on this instance. Used for resource based cross account/region access. | list(string) |
[] |
no |
bus_policy_docs | List of additional IAM policy documents to append to the access policy for this instance. Ignored if using a partner bus. Generally you will want to use allow_put_events_arns over this. |
list(string) |
[] |
no |
cross_bus_rules | List of cross bus routing rules. | list( |
[] |
no |
enable_schema_discovery_registry | Enable the EventBridge schema discovery resource. | bool |
true |
no |
name | The name of the eventbus or partner source. This must be unique per region per account. | string |
n/a | yes |
tags | Tags for resources created by module. | map(string) |
n/a | yes |
Name | Description |
---|---|
bus | The bus resource created by this module. |
cross_bus_rules_arns | ARNs of cross bus rules created for this bus. |
discoverer_arn | ARN of the EventBridge Schema Discover. |