A step-by-step guide to cross-account and cross-region events with EventBridge

6 minute read
Content level: Intermediate
3

The article focuses on EventBridge and provides a step-by-step guide for simplifying the orchestration of event-driven architectures across multiple accounts and regions.

Event-driven architectures (EDAs) have revolutionized how software systems are built, enabling efficient communication, low coupling and scalability. However, managing events across multiple accounts and regions has traditionally been complex and challenging. That is where EventBridge comes in. This article provides a step-by-step guide on how EventBridge simplifies orchestrating event-driven architectures, enabling cross-account and cross-region event routing.

Architecture

The architecture involves three accounts:

  • AccountA: the source event account with a Lambda function that sends events.
  • AccountGlobal: the account hosting the global Event bus and forwarding rule to the target account.
  • AccountB: the target event account containing our target workload, a Lambda function.

EDA Architecture

The flow has four steps:

  1. EventSender Lambda is triggered.
  2. EventSender Lambda sends an event towards the global event bus.
  3. Global event bus forwards the event to a target event bus.
  4. The target event bus forwards the event to Event Receiver Lambda.

Prerequisite: Multi-account setup via Organizations

The easiest way to set up accounts is via AWS Organizations.

  • Go to AWS Organizations and create an Organization

  • Start adding or inviting AWS accounts

AWS Organizations

  • Create AccountA, AccountB and AccountGlobal similarly.

Add accounts to Organizations

  • Optionally, you can place the accounts under Organizational Units (OUs) for better management.

  • The Organizational structure should look as this.

AWS Organization structure

For tutorials/troubleshooting on AWS Organizations (out of the scope of this article), please refer to the following:

Finally, please take note of the respective AWS account ids, and let’s start the steps.

Steps

1. Setup Global Account

  • Login to AccountGlobal

  • Select Ireland region (eu-west-1)

  • In EventBridge, create a custom Event bus named event-bus-global

  • Associate following Resource-based policy and replace placeholders with correct AWS account IDs:

    {
      "Version": "2012–10–17",
      "Statement": [{
        "Sid": "allow_account_a_to_put_events",
        "Effect": "Allow",
        "Principal": {
          "AWS": "arn:aws:iam::<ACCOUNT_A_ID>:root"
        },
        "Action": "events:PutEvents",
        "Resource": "arn:aws:events:eu-west-1:<ACCOUNT_GLOBAL_ID>:event-bus/event-bus-global"
      }]
    }
  • If you experience issues with the above, click Load template and modify accordingly:

Load template section

  • Click Create, and the custom bus is created.

  • Take note of the event bus Amazon Resource Name (ARN).

2. Setup Account A (Sender)

  • Login to AccountA

  • Select Ireland region (eu-west-1)

  • In Lambda, create a NodeJS 18.x Lambda Function called eventSender

Create Lambda function screen

  • Add the following code. The code leverages the AWS SDK EventBridge client library to send a trivial JSON payload to the global Event bus, identified by its ARN. Event “Source” and “DetailType” will be used later to filter the event and forward it to appropriate targets.
    import { EventBridgeClient, PutEventsCommand } from “@aws-sdk/client-eventbridge”;
    
    export const handler = async(event) => {
     try {
       const eventBridge = new EventBridgeClient({ region: ‘eu-west-1’ });
       const eventParams = {
         Entries: [
           {
             Source: ‘event.sender.source’,
             DetailType: ‘EventA.Sent’,
             Detail: JSON.stringify({ type: ‘a’, value: ‘111’ }),
             EventBusName: ‘arn:aws:events:eu-west-1:<ACCOUNT_GLOBAL_ID>:event-bus/event-bus-global’
           }
         ]
       };
    
       await eventBridge.send(new PutEventsCommand(eventParams));
    
       return {
         statusCode: 200,
         body: ‘Event sent successfully’
       };
     } catch (err) {
        console.error(‘Failed to send event:’, err);
     
        return {
           statusCode: 500,
           body: ‘Failed to send event’
        };
     }
    };
  • Under Configuration -> Permissions, click on the IAM execution role and add the following custom policy to the role:
    {
      “Version”: “2012–10–17”,
      “Statement”: [
        {
          “Effect”: “Allow”,
          “Action”: [“events:PutEvents”],
          “Resource”: [
            “arn:aws:events:eu-west-1:<ACCOUNT_GLOBAL_ID>:event-bus/event-bus-global”
          ]
        }
      ]
    }

3. Setup Account B (Receiver)

  • Login to AccountB

  • In EventBridge, create a custom Event Bus named event-bus-account-b in a different region than AccountA bus and sender, e.g. Stockholm (eu-north-1)

  • Associate following Resource-based policy:

    {
     "Version": "2012–10–17",
     "Statement": [{
     "Sid": "allow_account_to_put_events",
     "Effect": "Allow",
     "Principal": {
       "AWS": "arn:aws:iam::<ACCOUNT_GLOBAL_ID>:root"
     },
     "Action": "events:PutEvents",
     "Resource": "arn:aws:events:eu-north-1:<ACCOUNT_B_ID>:event-bus/event-bus-account-b"
     }]
    }
  • In Lambda, create a NodeJS 18.x Lambda function, as usual, called EventReceiver:
    export const handler = async(event) => {
      console.log(“Event received: “, event);
     
      const response = {
        statusCode: 200,
        body: JSON.stringify(‘Hello from Lambda!’),
      };
     
      return response;
    };

4. Glue the accounts via Rules

Now it is time to use EventBridge rules to link events between accounts. We will need two rules.

4.1 Setup the rule in the global account

  • In AccountGlobal, create an event rule named global-to-account-b, associated with the custom event bus (not the default one).

  • Select the Creation method *“Custom pattern (JSON editor)” *during the wizard **and create the following Event Pattern, which matches any event coming from the source and detail type sent from the Lambda EventSender, in AccountA.

    {
     “source”: [“event.sender.source”],
     “detail-type”: [“EventA.Sent”]
    }

Event pattern section

  • The target type is another EventBridge event bus (event-bus-account-b), which lives in a different account and a different region (eu-north-1) than the global one (eu-west-1). Pick the event bus ARN from AccountB.

EventBridge cross-account configuration

  • Move forward and Create the rule.

4.2 Setup the rule in the AccountB

  • In AccountB, create an event rule named account-b-to-target, associated with the custom event bus (not the default one),

  • Fill in the same Event Pattern as the previous step above.

  • This time, the target type is the Lambda function, named EventReceiver, previously created in AccountB.

Enter image description here

  • Move forward until the rule is created.

Verification

To verify that EventSender in AccountA (eu-west-1) sends an event to EventReceiver in AccountB (eu-north-1) via a global bus (eu-west-1), just trigger the EventSender lambda function.

In AccountB, go to the CloudWatch log group associated with the target function (EventReceiver), and the following log will prove the event's successful reception across accounts and regions.

Cloudwatch logs

Summary

In conclusion, this article demonstrated that EventBridge’s cross-account and cross-region event capabilities provide a straightforward and efficient solution for managing workloads and orchestrating event-driven architectures.

As the next step, implement the above via IaC, such as CDK, have fun!

profile picture
EXPERT
published a year ago15597 views