The aws:cloudwatch/eventBusPolicy:EventBusPolicy resource, part of the Pulumi AWS provider, attaches a resource policy to an EventBridge event bus, controlling which AWS accounts and organizations can send or read events. This guide focuses on three capabilities: cross-account event delivery, organization-scoped access, and multi-statement policies.
Event bus policies reference an existing event bus by name and may use AWS Organization IDs for condition-based access. The examples are intentionally small. Combine them with your own event bus infrastructure and account topology.
Grant a specific account permission to send events
Cross-account event delivery starts by granting a trusted AWS account permission to call PutEvents on your event bus.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const test = aws.iam.getPolicyDocument({
statements: [{
sid: "DevAccountAccess",
effect: "Allow",
actions: ["events:PutEvents"],
resources: ["arn:aws:events:eu-west-1:123456789012:event-bus/default"],
principals: [{
type: "AWS",
identifiers: ["123456789012"],
}],
}],
});
const testEventBusPolicy = new aws.cloudwatch.EventBusPolicy("test", {
policy: test.then(test => test.json),
eventBusName: testAwsCloudwatchEventBus.name,
});
import pulumi
import pulumi_aws as aws
test = aws.iam.get_policy_document(statements=[{
"sid": "DevAccountAccess",
"effect": "Allow",
"actions": ["events:PutEvents"],
"resources": ["arn:aws:events:eu-west-1:123456789012:event-bus/default"],
"principals": [{
"type": "AWS",
"identifiers": ["123456789012"],
}],
}])
test_event_bus_policy = aws.cloudwatch.EventBusPolicy("test",
policy=test.json,
event_bus_name=test_aws_cloudwatch_event_bus["name"])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudwatch"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
test, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
Statements: []iam.GetPolicyDocumentStatement{
{
Sid: pulumi.StringRef("DevAccountAccess"),
Effect: pulumi.StringRef("Allow"),
Actions: []string{
"events:PutEvents",
},
Resources: []string{
"arn:aws:events:eu-west-1:123456789012:event-bus/default",
},
Principals: []iam.GetPolicyDocumentStatementPrincipal{
{
Type: "AWS",
Identifiers: []string{
"123456789012",
},
},
},
},
},
}, nil)
if err != nil {
return err
}
_, err = cloudwatch.NewEventBusPolicy(ctx, "test", &cloudwatch.EventBusPolicyArgs{
Policy: pulumi.String(test.Json),
EventBusName: pulumi.Any(testAwsCloudwatchEventBus.Name),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var test = Aws.Iam.GetPolicyDocument.Invoke(new()
{
Statements = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
{
Sid = "DevAccountAccess",
Effect = "Allow",
Actions = new[]
{
"events:PutEvents",
},
Resources = new[]
{
"arn:aws:events:eu-west-1:123456789012:event-bus/default",
},
Principals = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
{
Type = "AWS",
Identifiers = new[]
{
"123456789012",
},
},
},
},
},
});
var testEventBusPolicy = new Aws.CloudWatch.EventBusPolicy("test", new()
{
Policy = test.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
EventBusName = testAwsCloudwatchEventBus.Name,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.cloudwatch.EventBusPolicy;
import com.pulumi.aws.cloudwatch.EventBusPolicyArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var test = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
.statements(GetPolicyDocumentStatementArgs.builder()
.sid("DevAccountAccess")
.effect("Allow")
.actions("events:PutEvents")
.resources("arn:aws:events:eu-west-1:123456789012:event-bus/default")
.principals(GetPolicyDocumentStatementPrincipalArgs.builder()
.type("AWS")
.identifiers("123456789012")
.build())
.build())
.build());
var testEventBusPolicy = new EventBusPolicy("testEventBusPolicy", EventBusPolicyArgs.builder()
.policy(test.json())
.eventBusName(testAwsCloudwatchEventBus.name())
.build());
}
}
resources:
testEventBusPolicy:
type: aws:cloudwatch:EventBusPolicy
name: test
properties:
policy: ${test.json}
eventBusName: ${testAwsCloudwatchEventBus.name}
variables:
test:
fn::invoke:
function: aws:iam:getPolicyDocument
arguments:
statements:
- sid: DevAccountAccess
effect: Allow
actions:
- events:PutEvents
resources:
- arn:aws:events:eu-west-1:123456789012:event-bus/default
principals:
- type: AWS
identifiers:
- '123456789012'
The policy property accepts an IAM policy document in JSON format. The getPolicyDocument function builds the policy with a statement that allows the specified account (via principals) to call PutEvents on your event bus. The eventBusName property identifies which bus receives the policy.
Allow organization members to read event bus metadata
AWS Organizations can centralize event routing by allowing member accounts to discover and inspect rules without granting write access.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const test = aws.iam.getPolicyDocument({
statements: [{
sid: "OrganizationAccess",
effect: "Allow",
actions: [
"events:DescribeRule",
"events:ListRules",
"events:ListTargetsByRule",
"events:ListTagsForResource",
],
resources: [
"arn:aws:events:eu-west-1:123456789012:rule/*",
"arn:aws:events:eu-west-1:123456789012:event-bus/default",
],
principals: [{
type: "AWS",
identifiers: ["*"],
}],
conditions: [{
test: "StringEquals",
variable: "aws:PrincipalOrgID",
values: [example.id],
}],
}],
});
const testEventBusPolicy = new aws.cloudwatch.EventBusPolicy("test", {
policy: test.then(test => test.json),
eventBusName: testAwsCloudwatchEventBus.name,
});
import pulumi
import pulumi_aws as aws
test = aws.iam.get_policy_document(statements=[{
"sid": "OrganizationAccess",
"effect": "Allow",
"actions": [
"events:DescribeRule",
"events:ListRules",
"events:ListTargetsByRule",
"events:ListTagsForResource",
],
"resources": [
"arn:aws:events:eu-west-1:123456789012:rule/*",
"arn:aws:events:eu-west-1:123456789012:event-bus/default",
],
"principals": [{
"type": "AWS",
"identifiers": ["*"],
}],
"conditions": [{
"test": "StringEquals",
"variable": "aws:PrincipalOrgID",
"values": [example["id"]],
}],
}])
test_event_bus_policy = aws.cloudwatch.EventBusPolicy("test",
policy=test.json,
event_bus_name=test_aws_cloudwatch_event_bus["name"])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudwatch"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
test, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
Statements: []iam.GetPolicyDocumentStatement{
{
Sid: pulumi.StringRef("OrganizationAccess"),
Effect: pulumi.StringRef("Allow"),
Actions: []string{
"events:DescribeRule",
"events:ListRules",
"events:ListTargetsByRule",
"events:ListTagsForResource",
},
Resources: []string{
"arn:aws:events:eu-west-1:123456789012:rule/*",
"arn:aws:events:eu-west-1:123456789012:event-bus/default",
},
Principals: []iam.GetPolicyDocumentStatementPrincipal{
{
Type: "AWS",
Identifiers: []string{
"*",
},
},
},
Conditions: []iam.GetPolicyDocumentStatementCondition{
{
Test: "StringEquals",
Variable: "aws:PrincipalOrgID",
Values: interface{}{
example.Id,
},
},
},
},
},
}, nil);
if err != nil {
return err
}
_, err = cloudwatch.NewEventBusPolicy(ctx, "test", &cloudwatch.EventBusPolicyArgs{
Policy: pulumi.String(test.Json),
EventBusName: pulumi.Any(testAwsCloudwatchEventBus.Name),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var test = Aws.Iam.GetPolicyDocument.Invoke(new()
{
Statements = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
{
Sid = "OrganizationAccess",
Effect = "Allow",
Actions = new[]
{
"events:DescribeRule",
"events:ListRules",
"events:ListTargetsByRule",
"events:ListTagsForResource",
},
Resources = new[]
{
"arn:aws:events:eu-west-1:123456789012:rule/*",
"arn:aws:events:eu-west-1:123456789012:event-bus/default",
},
Principals = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
{
Type = "AWS",
Identifiers = new[]
{
"*",
},
},
},
Conditions = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementConditionInputArgs
{
Test = "StringEquals",
Variable = "aws:PrincipalOrgID",
Values = new[]
{
example.Id,
},
},
},
},
},
});
var testEventBusPolicy = new Aws.CloudWatch.EventBusPolicy("test", new()
{
Policy = test.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
EventBusName = testAwsCloudwatchEventBus.Name,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.cloudwatch.EventBusPolicy;
import com.pulumi.aws.cloudwatch.EventBusPolicyArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var test = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
.statements(GetPolicyDocumentStatementArgs.builder()
.sid("OrganizationAccess")
.effect("Allow")
.actions(
"events:DescribeRule",
"events:ListRules",
"events:ListTargetsByRule",
"events:ListTagsForResource")
.resources(
"arn:aws:events:eu-west-1:123456789012:rule/*",
"arn:aws:events:eu-west-1:123456789012:event-bus/default")
.principals(GetPolicyDocumentStatementPrincipalArgs.builder()
.type("AWS")
.identifiers("*")
.build())
.conditions(GetPolicyDocumentStatementConditionArgs.builder()
.test("StringEquals")
.variable("aws:PrincipalOrgID")
.values(example.id())
.build())
.build())
.build());
var testEventBusPolicy = new EventBusPolicy("testEventBusPolicy", EventBusPolicyArgs.builder()
.policy(test.json())
.eventBusName(testAwsCloudwatchEventBus.name())
.build());
}
}
resources:
testEventBusPolicy:
type: aws:cloudwatch:EventBusPolicy
name: test
properties:
policy: ${test.json}
eventBusName: ${testAwsCloudwatchEventBus.name}
variables:
test:
fn::invoke:
function: aws:iam:getPolicyDocument
arguments:
statements:
- sid: OrganizationAccess
effect: Allow
actions:
- events:DescribeRule
- events:ListRules
- events:ListTargetsByRule
- events:ListTagsForResource
resources:
- arn:aws:events:eu-west-1:123456789012:rule/*
- arn:aws:events:eu-west-1:123456789012:event-bus/default
principals:
- type: AWS
identifiers:
- '*'
conditions:
- test: StringEquals
variable: aws:PrincipalOrgID
values:
- ${example.id}
The conditions block restricts access to accounts within your organization using the aws:PrincipalOrgID condition key. The actions list includes read-only operations like DescribeRule and ListRules, enabling compliance scanning without write permissions. The principals field uses a wildcard with the condition to match any account in the organization.
Combine account and organization access in one policy
Complex event architectures often need both specific account permissions and organization-wide read access.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const test = aws.iam.getPolicyDocument({
statements: [
{
sid: "DevAccountAccess",
effect: "Allow",
actions: ["events:PutEvents"],
resources: ["arn:aws:events:eu-west-1:123456789012:event-bus/default"],
principals: [{
type: "AWS",
identifiers: ["123456789012"],
}],
},
{
sid: "OrganizationAccess",
effect: "Allow",
actions: [
"events:DescribeRule",
"events:ListRules",
"events:ListTargetsByRule",
"events:ListTagsForResource",
],
resources: [
"arn:aws:events:eu-west-1:123456789012:rule/*",
"arn:aws:events:eu-west-1:123456789012:event-bus/default",
],
principals: [{
type: "AWS",
identifiers: ["*"],
}],
conditions: [{
test: "StringEquals",
variable: "aws:PrincipalOrgID",
values: [example.id],
}],
},
],
});
const testEventBusPolicy = new aws.cloudwatch.EventBusPolicy("test", {
policy: test.then(test => test.json),
eventBusName: testAwsCloudwatchEventBus.name,
});
import pulumi
import pulumi_aws as aws
test = aws.iam.get_policy_document(statements=[
{
"sid": "DevAccountAccess",
"effect": "Allow",
"actions": ["events:PutEvents"],
"resources": ["arn:aws:events:eu-west-1:123456789012:event-bus/default"],
"principals": [{
"type": "AWS",
"identifiers": ["123456789012"],
}],
},
{
"sid": "OrganizationAccess",
"effect": "Allow",
"actions": [
"events:DescribeRule",
"events:ListRules",
"events:ListTargetsByRule",
"events:ListTagsForResource",
],
"resources": [
"arn:aws:events:eu-west-1:123456789012:rule/*",
"arn:aws:events:eu-west-1:123456789012:event-bus/default",
],
"principals": [{
"type": "AWS",
"identifiers": ["*"],
}],
"conditions": [{
"test": "StringEquals",
"variable": "aws:PrincipalOrgID",
"values": [example["id"]],
}],
},
])
test_event_bus_policy = aws.cloudwatch.EventBusPolicy("test",
policy=test.json,
event_bus_name=test_aws_cloudwatch_event_bus["name"])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudwatch"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
test, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
Statements: []iam.GetPolicyDocumentStatement{
{
Sid: pulumi.StringRef("DevAccountAccess"),
Effect: pulumi.StringRef("Allow"),
Actions: []string{
"events:PutEvents",
},
Resources: []string{
"arn:aws:events:eu-west-1:123456789012:event-bus/default",
},
Principals: []iam.GetPolicyDocumentStatementPrincipal{
{
Type: "AWS",
Identifiers: []string{
"123456789012",
},
},
},
},
{
Sid: pulumi.StringRef("OrganizationAccess"),
Effect: pulumi.StringRef("Allow"),
Actions: []string{
"events:DescribeRule",
"events:ListRules",
"events:ListTargetsByRule",
"events:ListTagsForResource",
},
Resources: []string{
"arn:aws:events:eu-west-1:123456789012:rule/*",
"arn:aws:events:eu-west-1:123456789012:event-bus/default",
},
Principals: []iam.GetPolicyDocumentStatementPrincipal{
{
Type: "AWS",
Identifiers: []string{
"*",
},
},
},
Conditions: []iam.GetPolicyDocumentStatementCondition{
{
Test: "StringEquals",
Variable: "aws:PrincipalOrgID",
Values: interface{}{
example.Id,
},
},
},
},
},
}, nil);
if err != nil {
return err
}
_, err = cloudwatch.NewEventBusPolicy(ctx, "test", &cloudwatch.EventBusPolicyArgs{
Policy: pulumi.String(test.Json),
EventBusName: pulumi.Any(testAwsCloudwatchEventBus.Name),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var test = Aws.Iam.GetPolicyDocument.Invoke(new()
{
Statements = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
{
Sid = "DevAccountAccess",
Effect = "Allow",
Actions = new[]
{
"events:PutEvents",
},
Resources = new[]
{
"arn:aws:events:eu-west-1:123456789012:event-bus/default",
},
Principals = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
{
Type = "AWS",
Identifiers = new[]
{
"123456789012",
},
},
},
},
new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
{
Sid = "OrganizationAccess",
Effect = "Allow",
Actions = new[]
{
"events:DescribeRule",
"events:ListRules",
"events:ListTargetsByRule",
"events:ListTagsForResource",
},
Resources = new[]
{
"arn:aws:events:eu-west-1:123456789012:rule/*",
"arn:aws:events:eu-west-1:123456789012:event-bus/default",
},
Principals = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
{
Type = "AWS",
Identifiers = new[]
{
"*",
},
},
},
Conditions = new[]
{
new Aws.Iam.Inputs.GetPolicyDocumentStatementConditionInputArgs
{
Test = "StringEquals",
Variable = "aws:PrincipalOrgID",
Values = new[]
{
example.Id,
},
},
},
},
},
});
var testEventBusPolicy = new Aws.CloudWatch.EventBusPolicy("test", new()
{
Policy = test.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
EventBusName = testAwsCloudwatchEventBus.Name,
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.cloudwatch.EventBusPolicy;
import com.pulumi.aws.cloudwatch.EventBusPolicyArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var test = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
.statements(
GetPolicyDocumentStatementArgs.builder()
.sid("DevAccountAccess")
.effect("Allow")
.actions("events:PutEvents")
.resources("arn:aws:events:eu-west-1:123456789012:event-bus/default")
.principals(GetPolicyDocumentStatementPrincipalArgs.builder()
.type("AWS")
.identifiers("123456789012")
.build())
.build(),
GetPolicyDocumentStatementArgs.builder()
.sid("OrganizationAccess")
.effect("Allow")
.actions(
"events:DescribeRule",
"events:ListRules",
"events:ListTargetsByRule",
"events:ListTagsForResource")
.resources(
"arn:aws:events:eu-west-1:123456789012:rule/*",
"arn:aws:events:eu-west-1:123456789012:event-bus/default")
.principals(GetPolicyDocumentStatementPrincipalArgs.builder()
.type("AWS")
.identifiers("*")
.build())
.conditions(GetPolicyDocumentStatementConditionArgs.builder()
.test("StringEquals")
.variable("aws:PrincipalOrgID")
.values(example.id())
.build())
.build())
.build());
var testEventBusPolicy = new EventBusPolicy("testEventBusPolicy", EventBusPolicyArgs.builder()
.policy(test.json())
.eventBusName(testAwsCloudwatchEventBus.name())
.build());
}
}
resources:
testEventBusPolicy:
type: aws:cloudwatch:EventBusPolicy
name: test
properties:
policy: ${test.json}
eventBusName: ${testAwsCloudwatchEventBus.name}
variables:
test:
fn::invoke:
function: aws:iam:getPolicyDocument
arguments:
statements:
- sid: DevAccountAccess
effect: Allow
actions:
- events:PutEvents
resources:
- arn:aws:events:eu-west-1:123456789012:event-bus/default
principals:
- type: AWS
identifiers:
- '123456789012'
- sid: OrganizationAccess
effect: Allow
actions:
- events:DescribeRule
- events:ListRules
- events:ListTargetsByRule
- events:ListTagsForResource
resources:
- arn:aws:events:eu-west-1:123456789012:rule/*
- arn:aws:events:eu-west-1:123456789012:event-bus/default
principals:
- type: AWS
identifiers:
- '*'
conditions:
- test: StringEquals
variable: aws:PrincipalOrgID
values:
- ${example.id}
A single policy document can contain multiple statements, each with its own sid (statement ID), principals, and actions. This example grants PutEvents to one specific account while allowing all organization members to read event bus metadata. Each statement evaluates independently; the policy grants the union of all allowed actions.
Beyond these examples
These snippets focus on specific event bus policy features: cross-account event delivery, organization-scoped access control, and multi-statement policy documents. They’re intentionally minimal rather than full event routing architectures.
The examples reference pre-existing infrastructure such as an EventBridge event bus (by name) and AWS Organization ID for organization-scoped policies. They focus on attaching policies rather than provisioning the event bus itself.
To keep things focused, common policy patterns are omitted, including:
- Condition keys beyond aws:PrincipalOrgID
- Deny statements for explicit restrictions
- Resource-level permissions for specific rules
- Integration with EventPermission resource (incompatible)
These omissions are intentional: the goal is to illustrate how event bus policies are wired, not provide drop-in event routing modules. See the EventBridge EventBusPolicy resource reference for all available configuration options.
Let's configure AWS EventBridge Bus Policies
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Resource Compatibility & Limitations
aws.cloudwatch.EventBusPolicy is incompatible with aws.cloudwatch.EventPermission and will overwrite any permissions set by EventPermission. Choose one resource type for managing permissions on your event bus.eventBusName is immutable and cannot be changed after creation. Changing it requires replacing the resource.Configuration & Defaults
default event bus if you omit eventBusName.Cross-Account & Organization Access
events:PutEvents action and specify the account ID in principals.identifiers. Use aws.iam.getPolicyDocument to generate the policy JSON.principals to * and add a condition with test: "StringEquals", variable: "aws:PrincipalOrgID", and your organization ID in values. This restricts access to accounts within your organization.aws.iam.getPolicyDocument and use the resulting JSON for the policy property. This allows combining different access patterns (like account-specific and organization-wide) in a single resource.Using a different cloud?
Explore integration guides for other cloud providers: