The aws:cloudwatch/eventBusPolicy:EventBusPolicy resource, part of the Pulumi AWS provider, attaches resource-based policies to EventBridge event buses to control cross-account and organization-wide access. This guide focuses on three capabilities: cross-account event delivery, organization-scoped access control, and multi-statement policy documents.
Event bus policies reference existing event buses by name and may use AWS Organization IDs for condition-based access. The examples are intentionally small. Combine them with your own event buses, rules, and targets.
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 that defines who can access the event bus and what actions they can perform. The principals block specifies the trusted account ID, and the actions array grants PutEvents permission. This allows the remote account to publish events into your EventBridge infrastructure.
Grant organization-wide read access with conditions
Organizations often need to allow all member accounts to inspect rules and targets without granting write permissions.
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 using the aws:PrincipalOrgID key, which matches against your AWS Organization ID. This grants read-only actions (DescribeRule, ListRules, ListTargetsByRule, ListTagsForResource) to any account in your organization while blocking PutEvents. The wildcard principal ("*") combined with the organization condition creates organization-scoped access.
Combine account-specific and organization-wide permissions
Some deployments need both targeted write access for specific accounts and broad read access for the entire organization.
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}
Multiple statements in the policy document let you grant different permissions to different principals. The first statement gives a specific account PutEvents permission, while the second grants organization-wide read access. This pattern extends the previous examples by combining account-specific write access with organization-scoped read access in a single policy.
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-driven architectures.
The examples reference pre-existing infrastructure such as EventBridge event buses (referenced by name) and AWS Organization IDs (for organization-scoped policies). They focus on configuring access control rather than provisioning the event routing infrastructure.
To keep things focused, common EventBridge patterns are omitted, including:
- Event pattern filtering and content-based routing
- Event archive and replay configuration
- Dead letter queue setup for failed deliveries
- Cross-region event routing
These omissions are intentional: the goal is to illustrate how event bus access control is wired, not provide drop-in event-driven 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 permissions. Choose one resource type for managing event bus permissions.eventBusName is immutable and cannot be changed after resource creation. Changing it requires replacing the resource.Cross-Account & Organization Access
events:PutEvents action and specify the account ID in the principals block. Use aws.iam.getPolicyDocument to generate the policy JSON.aws:PrincipalOrgID to restrict access to your AWS Organization. Set principals to ["*"] and add the organization ID condition.Configuration & Defaults
eventBusName, the permissions are set on the default event bus.Using a different cloud?
Explore integration guides for other cloud providers: