Configure AWS EventBridge Targets

The aws:cloudwatch/eventTarget:EventTarget resource, part of the Pulumi AWS provider, connects EventBridge rules to AWS services that process events: Kinesis streams, Lambda functions, ECS tasks, API Gateway endpoints, and more. This guide focuses on three capabilities: routing events to different target types, transforming event data for targets, and cross-account event forwarding.

Event targets depend on EventBridge rules to trigger them, IAM roles with appropriate permissions, and the target resources themselves. The examples are intentionally small. Combine them with your own rules, IAM policies, and target infrastructure.

Stream events to Kinesis for processing

Many event-driven architectures route EventBridge events to Kinesis streams for buffering, ordering, and downstream processing.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const console = new aws.cloudwatch.EventRule("console", {
    name: "capture-ec2-scaling-events",
    description: "Capture all EC2 scaling events",
    eventPattern: JSON.stringify({
        source: ["aws.autoscaling"],
        "detail-type": [
            "EC2 Instance Launch Successful",
            "EC2 Instance Terminate Successful",
            "EC2 Instance Launch Unsuccessful",
            "EC2 Instance Terminate Unsuccessful",
        ],
    }),
});
const testStream = new aws.kinesis.Stream("test_stream", {
    name: "kinesis-test",
    shardCount: 1,
});
const yada = new aws.cloudwatch.EventTarget("yada", {
    targetId: "Yada",
    rule: console.name,
    arn: testStream.arn,
    runCommandTargets: [
        {
            key: "tag:Name",
            values: ["FooBar"],
        },
        {
            key: "InstanceIds",
            values: ["i-162058cd308bffec2"],
        },
    ],
});
import pulumi
import json
import pulumi_aws as aws

console = aws.cloudwatch.EventRule("console",
    name="capture-ec2-scaling-events",
    description="Capture all EC2 scaling events",
    event_pattern=json.dumps({
        "source": ["aws.autoscaling"],
        "detail-type": [
            "EC2 Instance Launch Successful",
            "EC2 Instance Terminate Successful",
            "EC2 Instance Launch Unsuccessful",
            "EC2 Instance Terminate Unsuccessful",
        ],
    }))
test_stream = aws.kinesis.Stream("test_stream",
    name="kinesis-test",
    shard_count=1)
yada = aws.cloudwatch.EventTarget("yada",
    target_id="Yada",
    rule=console.name,
    arn=test_stream.arn,
    run_command_targets=[
        {
            "key": "tag:Name",
            "values": ["FooBar"],
        },
        {
            "key": "InstanceIds",
            "values": ["i-162058cd308bffec2"],
        },
    ])
package main

import (
	"encoding/json"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudwatch"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kinesis"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		tmpJSON0, err := json.Marshal(map[string]interface{}{
			"source": []string{
				"aws.autoscaling",
			},
			"detail-type": []string{
				"EC2 Instance Launch Successful",
				"EC2 Instance Terminate Successful",
				"EC2 Instance Launch Unsuccessful",
				"EC2 Instance Terminate Unsuccessful",
			},
		})
		if err != nil {
			return err
		}
		json0 := string(tmpJSON0)
		console, err := cloudwatch.NewEventRule(ctx, "console", &cloudwatch.EventRuleArgs{
			Name:         pulumi.String("capture-ec2-scaling-events"),
			Description:  pulumi.String("Capture all EC2 scaling events"),
			EventPattern: pulumi.String(json0),
		})
		if err != nil {
			return err
		}
		testStream, err := kinesis.NewStream(ctx, "test_stream", &kinesis.StreamArgs{
			Name:       pulumi.String("kinesis-test"),
			ShardCount: pulumi.Int(1),
		})
		if err != nil {
			return err
		}
		_, err = cloudwatch.NewEventTarget(ctx, "yada", &cloudwatch.EventTargetArgs{
			TargetId: pulumi.String("Yada"),
			Rule:     console.Name,
			Arn:      testStream.Arn,
			RunCommandTargets: cloudwatch.EventTargetRunCommandTargetArray{
				&cloudwatch.EventTargetRunCommandTargetArgs{
					Key: pulumi.String("tag:Name"),
					Values: pulumi.StringArray{
						pulumi.String("FooBar"),
					},
				},
				&cloudwatch.EventTargetRunCommandTargetArgs{
					Key: pulumi.String("InstanceIds"),
					Values: pulumi.StringArray{
						pulumi.String("i-162058cd308bffec2"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var console = new Aws.CloudWatch.EventRule("console", new()
    {
        Name = "capture-ec2-scaling-events",
        Description = "Capture all EC2 scaling events",
        EventPattern = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["source"] = new[]
            {
                "aws.autoscaling",
            },
            ["detail-type"] = new[]
            {
                "EC2 Instance Launch Successful",
                "EC2 Instance Terminate Successful",
                "EC2 Instance Launch Unsuccessful",
                "EC2 Instance Terminate Unsuccessful",
            },
        }),
    });

    var testStream = new Aws.Kinesis.Stream("test_stream", new()
    {
        Name = "kinesis-test",
        ShardCount = 1,
    });

    var yada = new Aws.CloudWatch.EventTarget("yada", new()
    {
        TargetId = "Yada",
        Rule = console.Name,
        Arn = testStream.Arn,
        RunCommandTargets = new[]
        {
            new Aws.CloudWatch.Inputs.EventTargetRunCommandTargetArgs
            {
                Key = "tag:Name",
                Values = new[]
                {
                    "FooBar",
                },
            },
            new Aws.CloudWatch.Inputs.EventTargetRunCommandTargetArgs
            {
                Key = "InstanceIds",
                Values = new[]
                {
                    "i-162058cd308bffec2",
                },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.cloudwatch.EventRule;
import com.pulumi.aws.cloudwatch.EventRuleArgs;
import com.pulumi.aws.kinesis.Stream;
import com.pulumi.aws.kinesis.StreamArgs;
import com.pulumi.aws.cloudwatch.EventTarget;
import com.pulumi.aws.cloudwatch.EventTargetArgs;
import com.pulumi.aws.cloudwatch.inputs.EventTargetRunCommandTargetArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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) {
        var console = new EventRule("console", EventRuleArgs.builder()
            .name("capture-ec2-scaling-events")
            .description("Capture all EC2 scaling events")
            .eventPattern(serializeJson(
                jsonObject(
                    jsonProperty("source", jsonArray("aws.autoscaling")),
                    jsonProperty("detail-type", jsonArray(
                        "EC2 Instance Launch Successful", 
                        "EC2 Instance Terminate Successful", 
                        "EC2 Instance Launch Unsuccessful", 
                        "EC2 Instance Terminate Unsuccessful"
                    ))
                )))
            .build());

        var testStream = new Stream("testStream", StreamArgs.builder()
            .name("kinesis-test")
            .shardCount(1)
            .build());

        var yada = new EventTarget("yada", EventTargetArgs.builder()
            .targetId("Yada")
            .rule(console.name())
            .arn(testStream.arn())
            .runCommandTargets(            
                EventTargetRunCommandTargetArgs.builder()
                    .key("tag:Name")
                    .values("FooBar")
                    .build(),
                EventTargetRunCommandTargetArgs.builder()
                    .key("InstanceIds")
                    .values("i-162058cd308bffec2")
                    .build())
            .build());

    }
}
resources:
  yada:
    type: aws:cloudwatch:EventTarget
    properties:
      targetId: Yada
      rule: ${console.name}
      arn: ${testStream.arn}
      runCommandTargets:
        - key: tag:Name
          values:
            - FooBar
        - key: InstanceIds
          values:
            - i-162058cd308bffec2
  console:
    type: aws:cloudwatch:EventRule
    properties:
      name: capture-ec2-scaling-events
      description: Capture all EC2 scaling events
      eventPattern:
        fn::toJSON:
          source:
            - aws.autoscaling
          detail-type:
            - EC2 Instance Launch Successful
            - EC2 Instance Terminate Successful
            - EC2 Instance Launch Unsuccessful
            - EC2 Instance Terminate Unsuccessful
  testStream:
    type: aws:kinesis:Stream
    name: test_stream
    properties:
      name: kinesis-test
      shardCount: 1

When the rule matches an event, EventBridge delivers it to the Kinesis stream specified in the arn property. The runCommandTargets property tags instances for SSM command execution, though this example focuses on Kinesis delivery. The targetId provides a unique identifier for this target within the rule.

Execute SSM documents on tagged instances

Operations teams use EventBridge to trigger Systems Manager commands on instances matching specific tags, enabling scheduled maintenance.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const ssmLifecycleTrust = aws.iam.getPolicyDocument({
    statements: [{
        actions: ["sts:AssumeRole"],
        principals: [{
            type: "Service",
            identifiers: ["events.amazonaws.com"],
        }],
    }],
});
const stopInstance = new aws.ssm.Document("stop_instance", {
    name: "stop_instance",
    documentType: "Command",
    content: JSON.stringify({
        schemaVersion: "1.2",
        description: "Stop an instance",
        parameters: {},
        runtimeConfig: {
            "aws:runShellScript": {
                properties: [{
                    id: "0.aws:runShellScript",
                    runCommand: ["halt"],
                }],
            },
        },
    }),
});
const ssmLifecycle = aws.iam.getPolicyDocumentOutput({
    statements: [
        {
            effect: "Allow",
            actions: ["ssm:SendCommand"],
            resources: ["arn:aws:ec2:eu-west-1:1234567890:instance/*"],
            conditions: [{
                test: "StringEquals",
                variable: "ec2:ResourceTag/Terminate",
                values: ["*"],
            }],
        },
        {
            effect: "Allow",
            actions: ["ssm:SendCommand"],
            resources: [stopInstance.arn],
        },
    ],
});
const ssmLifecycleRole = new aws.iam.Role("ssm_lifecycle", {
    name: "SSMLifecycle",
    assumeRolePolicy: ssmLifecycleTrust.then(ssmLifecycleTrust => ssmLifecycleTrust.json),
});
const ssmLifecyclePolicy = new aws.iam.Policy("ssm_lifecycle", {
    name: "SSMLifecycle",
    policy: ssmLifecycle.apply(ssmLifecycle => ssmLifecycle.json),
});
const ssmLifecycleRolePolicyAttachment = new aws.iam.RolePolicyAttachment("ssm_lifecycle", {
    policyArn: ssmLifecyclePolicy.arn,
    role: ssmLifecycleRole.name,
});
const stopInstances = new aws.cloudwatch.EventRule("stop_instances", {
    name: "StopInstance",
    description: "Stop instances nightly",
    scheduleExpression: "cron(0 0 * * ? *)",
});
const stopInstancesEventTarget = new aws.cloudwatch.EventTarget("stop_instances", {
    targetId: "StopInstance",
    arn: stopInstance.arn,
    rule: stopInstances.name,
    roleArn: ssmLifecycleRole.arn,
    runCommandTargets: [{
        key: "tag:Terminate",
        values: ["midnight"],
    }],
});
import pulumi
import json
import pulumi_aws as aws

ssm_lifecycle_trust = aws.iam.get_policy_document(statements=[{
    "actions": ["sts:AssumeRole"],
    "principals": [{
        "type": "Service",
        "identifiers": ["events.amazonaws.com"],
    }],
}])
stop_instance = aws.ssm.Document("stop_instance",
    name="stop_instance",
    document_type="Command",
    content=json.dumps({
        "schemaVersion": "1.2",
        "description": "Stop an instance",
        "parameters": {},
        "runtimeConfig": {
            "aws:runShellScript": {
                "properties": [{
                    "id": "0.aws:runShellScript",
                    "runCommand": ["halt"],
                }],
            },
        },
    }))
ssm_lifecycle = aws.iam.get_policy_document_output(statements=[
    {
        "effect": "Allow",
        "actions": ["ssm:SendCommand"],
        "resources": ["arn:aws:ec2:eu-west-1:1234567890:instance/*"],
        "conditions": [{
            "test": "StringEquals",
            "variable": "ec2:ResourceTag/Terminate",
            "values": ["*"],
        }],
    },
    {
        "effect": "Allow",
        "actions": ["ssm:SendCommand"],
        "resources": [stop_instance.arn],
    },
])
ssm_lifecycle_role = aws.iam.Role("ssm_lifecycle",
    name="SSMLifecycle",
    assume_role_policy=ssm_lifecycle_trust.json)
ssm_lifecycle_policy = aws.iam.Policy("ssm_lifecycle",
    name="SSMLifecycle",
    policy=ssm_lifecycle.json)
ssm_lifecycle_role_policy_attachment = aws.iam.RolePolicyAttachment("ssm_lifecycle",
    policy_arn=ssm_lifecycle_policy.arn,
    role=ssm_lifecycle_role.name)
stop_instances = aws.cloudwatch.EventRule("stop_instances",
    name="StopInstance",
    description="Stop instances nightly",
    schedule_expression="cron(0 0 * * ? *)")
stop_instances_event_target = aws.cloudwatch.EventTarget("stop_instances",
    target_id="StopInstance",
    arn=stop_instance.arn,
    rule=stop_instances.name,
    role_arn=ssm_lifecycle_role.arn,
    run_command_targets=[{
        "key": "tag:Terminate",
        "values": ["midnight"],
    }])
package main

import (
	"encoding/json"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudwatch"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ssm"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		ssmLifecycleTrust, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Actions: []string{
						"sts:AssumeRole",
					},
					Principals: []iam.GetPolicyDocumentStatementPrincipal{
						{
							Type: "Service",
							Identifiers: []string{
								"events.amazonaws.com",
							},
						},
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		tmpJSON0, err := json.Marshal(map[string]interface{}{
			"schemaVersion": "1.2",
			"description":   "Stop an instance",
			"parameters":    map[string]interface{}{},
			"runtimeConfig": map[string]interface{}{
				"aws:runShellScript": map[string]interface{}{
					"properties": []map[string]interface{}{
						map[string]interface{}{
							"id": "0.aws:runShellScript",
							"runCommand": []string{
								"halt",
							},
						},
					},
				},
			},
		})
		if err != nil {
			return err
		}
		json0 := string(tmpJSON0)
		stopInstance, err := ssm.NewDocument(ctx, "stop_instance", &ssm.DocumentArgs{
			Name:         pulumi.String("stop_instance"),
			DocumentType: pulumi.String("Command"),
			Content:      pulumi.String(json0),
		})
		if err != nil {
			return err
		}
		ssmLifecycle := iam.GetPolicyDocumentOutput(ctx, iam.GetPolicyDocumentOutputArgs{
			Statements: iam.GetPolicyDocumentStatementArray{
				&iam.GetPolicyDocumentStatementArgs{
					Effect: pulumi.String("Allow"),
					Actions: pulumi.StringArray{
						pulumi.String("ssm:SendCommand"),
					},
					Resources: pulumi.StringArray{
						pulumi.String("arn:aws:ec2:eu-west-1:1234567890:instance/*"),
					},
					Conditions: iam.GetPolicyDocumentStatementConditionArray{
						&iam.GetPolicyDocumentStatementConditionArgs{
							Test:     pulumi.String("StringEquals"),
							Variable: pulumi.String("ec2:ResourceTag/Terminate"),
							Values: pulumi.StringArray{
								pulumi.String("*"),
							},
						},
					},
				},
				&iam.GetPolicyDocumentStatementArgs{
					Effect: pulumi.String("Allow"),
					Actions: pulumi.StringArray{
						pulumi.String("ssm:SendCommand"),
					},
					Resources: pulumi.StringArray{
						stopInstance.Arn,
					},
				},
			},
		}, nil)
		ssmLifecycleRole, err := iam.NewRole(ctx, "ssm_lifecycle", &iam.RoleArgs{
			Name:             pulumi.String("SSMLifecycle"),
			AssumeRolePolicy: pulumi.String(ssmLifecycleTrust.Json),
		})
		if err != nil {
			return err
		}
		ssmLifecyclePolicy, err := iam.NewPolicy(ctx, "ssm_lifecycle", &iam.PolicyArgs{
			Name: pulumi.String("SSMLifecycle"),
			Policy: pulumi.String(ssmLifecycle.ApplyT(func(ssmLifecycle iam.GetPolicyDocumentResult) (*string, error) {
				return &ssmLifecycle.Json, nil
			}).(pulumi.StringPtrOutput)),
		})
		if err != nil {
			return err
		}
		_, err = iam.NewRolePolicyAttachment(ctx, "ssm_lifecycle", &iam.RolePolicyAttachmentArgs{
			PolicyArn: ssmLifecyclePolicy.Arn,
			Role:      ssmLifecycleRole.Name,
		})
		if err != nil {
			return err
		}
		stopInstances, err := cloudwatch.NewEventRule(ctx, "stop_instances", &cloudwatch.EventRuleArgs{
			Name:               pulumi.String("StopInstance"),
			Description:        pulumi.String("Stop instances nightly"),
			ScheduleExpression: pulumi.String("cron(0 0 * * ? *)"),
		})
		if err != nil {
			return err
		}
		_, err = cloudwatch.NewEventTarget(ctx, "stop_instances", &cloudwatch.EventTargetArgs{
			TargetId: pulumi.String("StopInstance"),
			Arn:      stopInstance.Arn,
			Rule:     stopInstances.Name,
			RoleArn:  ssmLifecycleRole.Arn,
			RunCommandTargets: cloudwatch.EventTargetRunCommandTargetArray{
				&cloudwatch.EventTargetRunCommandTargetArgs{
					Key: pulumi.String("tag:Terminate"),
					Values: pulumi.StringArray{
						pulumi.String("midnight"),
					},
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var ssmLifecycleTrust = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Actions = new[]
                {
                    "sts:AssumeRole",
                },
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "Service",
                        Identifiers = new[]
                        {
                            "events.amazonaws.com",
                        },
                    },
                },
            },
        },
    });

    var stopInstance = new Aws.Ssm.Document("stop_instance", new()
    {
        Name = "stop_instance",
        DocumentType = "Command",
        Content = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["schemaVersion"] = "1.2",
            ["description"] = "Stop an instance",
            ["parameters"] = new Dictionary<string, object?>
            {
            },
            ["runtimeConfig"] = new Dictionary<string, object?>
            {
                ["aws:runShellScript"] = new Dictionary<string, object?>
                {
                    ["properties"] = new[]
                    {
                        new Dictionary<string, object?>
                        {
                            ["id"] = "0.aws:runShellScript",
                            ["runCommand"] = new[]
                            {
                                "halt",
                            },
                        },
                    },
                },
            },
        }),
    });

    var ssmLifecycle = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Actions = new[]
                {
                    "ssm:SendCommand",
                },
                Resources = new[]
                {
                    "arn:aws:ec2:eu-west-1:1234567890:instance/*",
                },
                Conditions = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementConditionInputArgs
                    {
                        Test = "StringEquals",
                        Variable = "ec2:ResourceTag/Terminate",
                        Values = new[]
                        {
                            "*",
                        },
                    },
                },
            },
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Actions = new[]
                {
                    "ssm:SendCommand",
                },
                Resources = new[]
                {
                    stopInstance.Arn,
                },
            },
        },
    });

    var ssmLifecycleRole = new Aws.Iam.Role("ssm_lifecycle", new()
    {
        Name = "SSMLifecycle",
        AssumeRolePolicy = ssmLifecycleTrust.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var ssmLifecyclePolicy = new Aws.Iam.Policy("ssm_lifecycle", new()
    {
        Name = "SSMLifecycle",
        PolicyDocument = ssmLifecycle.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var ssmLifecycleRolePolicyAttachment = new Aws.Iam.RolePolicyAttachment("ssm_lifecycle", new()
    {
        PolicyArn = ssmLifecyclePolicy.Arn,
        Role = ssmLifecycleRole.Name,
    });

    var stopInstances = new Aws.CloudWatch.EventRule("stop_instances", new()
    {
        Name = "StopInstance",
        Description = "Stop instances nightly",
        ScheduleExpression = "cron(0 0 * * ? *)",
    });

    var stopInstancesEventTarget = new Aws.CloudWatch.EventTarget("stop_instances", new()
    {
        TargetId = "StopInstance",
        Arn = stopInstance.Arn,
        Rule = stopInstances.Name,
        RoleArn = ssmLifecycleRole.Arn,
        RunCommandTargets = new[]
        {
            new Aws.CloudWatch.Inputs.EventTargetRunCommandTargetArgs
            {
                Key = "tag:Terminate",
                Values = new[]
                {
                    "midnight",
                },
            },
        },
    });

});
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.ssm.Document;
import com.pulumi.aws.ssm.DocumentArgs;
import com.pulumi.aws.iam.Role;
import com.pulumi.aws.iam.RoleArgs;
import com.pulumi.aws.iam.Policy;
import com.pulumi.aws.iam.PolicyArgs;
import com.pulumi.aws.iam.RolePolicyAttachment;
import com.pulumi.aws.iam.RolePolicyAttachmentArgs;
import com.pulumi.aws.cloudwatch.EventRule;
import com.pulumi.aws.cloudwatch.EventRuleArgs;
import com.pulumi.aws.cloudwatch.EventTarget;
import com.pulumi.aws.cloudwatch.EventTargetArgs;
import com.pulumi.aws.cloudwatch.inputs.EventTargetRunCommandTargetArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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 ssmLifecycleTrust = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(GetPolicyDocumentStatementArgs.builder()
                .actions("sts:AssumeRole")
                .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                    .type("Service")
                    .identifiers("events.amazonaws.com")
                    .build())
                .build())
            .build());

        var stopInstance = new Document("stopInstance", DocumentArgs.builder()
            .name("stop_instance")
            .documentType("Command")
            .content(serializeJson(
                jsonObject(
                    jsonProperty("schemaVersion", "1.2"),
                    jsonProperty("description", "Stop an instance"),
                    jsonProperty("parameters", jsonObject(

                    )),
                    jsonProperty("runtimeConfig", jsonObject(
                        jsonProperty("aws:runShellScript", jsonObject(
                            jsonProperty("properties", jsonArray(jsonObject(
                                jsonProperty("id", "0.aws:runShellScript"),
                                jsonProperty("runCommand", jsonArray("halt"))
                            )))
                        ))
                    ))
                )))
            .build());

        final var ssmLifecycle = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(            
                GetPolicyDocumentStatementArgs.builder()
                    .effect("Allow")
                    .actions("ssm:SendCommand")
                    .resources("arn:aws:ec2:eu-west-1:1234567890:instance/*")
                    .conditions(GetPolicyDocumentStatementConditionArgs.builder()
                        .test("StringEquals")
                        .variable("ec2:ResourceTag/Terminate")
                        .values("*")
                        .build())
                    .build(),
                GetPolicyDocumentStatementArgs.builder()
                    .effect("Allow")
                    .actions("ssm:SendCommand")
                    .resources(stopInstance.arn())
                    .build())
            .build());

        var ssmLifecycleRole = new Role("ssmLifecycleRole", RoleArgs.builder()
            .name("SSMLifecycle")
            .assumeRolePolicy(ssmLifecycleTrust.json())
            .build());

        var ssmLifecyclePolicy = new Policy("ssmLifecyclePolicy", PolicyArgs.builder()
            .name("SSMLifecycle")
            .policy(ssmLifecycle.applyValue(_ssmLifecycle -> _ssmLifecycle.json()))
            .build());

        var ssmLifecycleRolePolicyAttachment = new RolePolicyAttachment("ssmLifecycleRolePolicyAttachment", RolePolicyAttachmentArgs.builder()
            .policyArn(ssmLifecyclePolicy.arn())
            .role(ssmLifecycleRole.name())
            .build());

        var stopInstances = new EventRule("stopInstances", EventRuleArgs.builder()
            .name("StopInstance")
            .description("Stop instances nightly")
            .scheduleExpression("cron(0 0 * * ? *)")
            .build());

        var stopInstancesEventTarget = new EventTarget("stopInstancesEventTarget", EventTargetArgs.builder()
            .targetId("StopInstance")
            .arn(stopInstance.arn())
            .rule(stopInstances.name())
            .roleArn(ssmLifecycleRole.arn())
            .runCommandTargets(EventTargetRunCommandTargetArgs.builder()
                .key("tag:Terminate")
                .values("midnight")
                .build())
            .build());

    }
}
resources:
  ssmLifecycleRole:
    type: aws:iam:Role
    name: ssm_lifecycle
    properties:
      name: SSMLifecycle
      assumeRolePolicy: ${ssmLifecycleTrust.json}
  ssmLifecyclePolicy:
    type: aws:iam:Policy
    name: ssm_lifecycle
    properties:
      name: SSMLifecycle
      policy: ${ssmLifecycle.json}
  ssmLifecycleRolePolicyAttachment:
    type: aws:iam:RolePolicyAttachment
    name: ssm_lifecycle
    properties:
      policyArn: ${ssmLifecyclePolicy.arn}
      role: ${ssmLifecycleRole.name}
  stopInstance:
    type: aws:ssm:Document
    name: stop_instance
    properties:
      name: stop_instance
      documentType: Command
      content:
        fn::toJSON:
          schemaVersion: '1.2'
          description: Stop an instance
          parameters: {}
          runtimeConfig:
            aws:runShellScript:
              properties:
                - id: 0.aws:runShellScript
                  runCommand:
                    - halt
  stopInstances:
    type: aws:cloudwatch:EventRule
    name: stop_instances
    properties:
      name: StopInstance
      description: Stop instances nightly
      scheduleExpression: cron(0 0 * * ? *)
  stopInstancesEventTarget:
    type: aws:cloudwatch:EventTarget
    name: stop_instances
    properties:
      targetId: StopInstance
      arn: ${stopInstance.arn}
      rule: ${stopInstances.name}
      roleArn: ${ssmLifecycleRole.arn}
      runCommandTargets:
        - key: tag:Terminate
          values:
            - midnight
variables:
  ssmLifecycleTrust:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - actions:
              - sts:AssumeRole
            principals:
              - type: Service
                identifiers:
                  - events.amazonaws.com
  ssmLifecycle:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            actions:
              - ssm:SendCommand
            resources:
              - arn:aws:ec2:eu-west-1:1234567890:instance/*
            conditions:
              - test: StringEquals
                variable: ec2:ResourceTag/Terminate
                values:
                  - '*'
          - effect: Allow
            actions:
              - ssm:SendCommand
            resources:
              - ${stopInstance.arn}

The runCommandTargets property selects instances by tag (key: “tag:Terminate”, values: [“midnight”]). EventBridge invokes the SSM document specified in arn, and the roleArn grants permissions to execute SSM commands. The schedule expression in the rule determines when commands run.

Launch ECS tasks with container overrides

Scheduled or event-driven workloads often run ECS tasks with custom commands that differ from task definition defaults.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";

const assumeRole = aws.iam.getPolicyDocument({
    statements: [{
        effect: "Allow",
        principals: [{
            type: "Service",
            identifiers: ["events.amazonaws.com"],
        }],
        actions: ["sts:AssumeRole"],
    }],
});
const ecsEvents = new aws.iam.Role("ecs_events", {
    name: "ecs_events",
    assumeRolePolicy: assumeRole.then(assumeRole => assumeRole.json),
});
const ecsEventsRunTaskWithAnyRole = std.replace({
    text: taskName.arn,
    search: "/:\\d+$/",
    replace: ":*",
}).then(invoke => aws.iam.getPolicyDocument({
    statements: [
        {
            effect: "Allow",
            actions: ["iam:PassRole"],
            resources: ["*"],
        },
        {
            effect: "Allow",
            actions: ["ecs:RunTask"],
            resources: [invoke.result],
        },
    ],
}));
const ecsEventsRunTaskWithAnyRoleRolePolicy = new aws.iam.RolePolicy("ecs_events_run_task_with_any_role", {
    name: "ecs_events_run_task_with_any_role",
    role: ecsEvents.id,
    policy: ecsEventsRunTaskWithAnyRole.then(ecsEventsRunTaskWithAnyRole => ecsEventsRunTaskWithAnyRole.json),
});
const ecsScheduledTask = new aws.cloudwatch.EventTarget("ecs_scheduled_task", {
    targetId: "run-scheduled-task-every-hour",
    arn: clusterName.arn,
    rule: everyHour.name,
    roleArn: ecsEvents.arn,
    ecsTarget: {
        taskCount: 1,
        taskDefinitionArn: taskName.arn,
    },
    input: JSON.stringify({
        containerOverrides: [{
            name: "name-of-container-to-override",
            command: [
                "bin/console",
                "scheduled-task",
            ],
        }],
    }),
});
import pulumi
import json
import pulumi_aws as aws
import pulumi_std as std

assume_role = aws.iam.get_policy_document(statements=[{
    "effect": "Allow",
    "principals": [{
        "type": "Service",
        "identifiers": ["events.amazonaws.com"],
    }],
    "actions": ["sts:AssumeRole"],
}])
ecs_events = aws.iam.Role("ecs_events",
    name="ecs_events",
    assume_role_policy=assume_role.json)
ecs_events_run_task_with_any_role = aws.iam.get_policy_document(statements=[
    {
        "effect": "Allow",
        "actions": ["iam:PassRole"],
        "resources": ["*"],
    },
    {
        "effect": "Allow",
        "actions": ["ecs:RunTask"],
        "resources": [std.replace(text=task_name["arn"],
            search="/:\\d+$/",
            replace=":*").result],
    },
])
ecs_events_run_task_with_any_role_role_policy = aws.iam.RolePolicy("ecs_events_run_task_with_any_role",
    name="ecs_events_run_task_with_any_role",
    role=ecs_events.id,
    policy=ecs_events_run_task_with_any_role.json)
ecs_scheduled_task = aws.cloudwatch.EventTarget("ecs_scheduled_task",
    target_id="run-scheduled-task-every-hour",
    arn=cluster_name["arn"],
    rule=every_hour["name"],
    role_arn=ecs_events.arn,
    ecs_target={
        "task_count": 1,
        "task_definition_arn": task_name["arn"],
    },
    input=json.dumps({
        "containerOverrides": [{
            "name": "name-of-container-to-override",
            "command": [
                "bin/console",
                "scheduled-task",
            ],
        }],
    }))
package main

import (
	"encoding/json"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudwatch"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/iam"
	"github.com/pulumi/pulumi-std/sdk/go/std"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
assumeRole, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
Statements: []iam.GetPolicyDocumentStatement{
{
Effect: pulumi.StringRef("Allow"),
Principals: []iam.GetPolicyDocumentStatementPrincipal{
{
Type: "Service",
Identifiers: []string{
"events.amazonaws.com",
},
},
},
Actions: []string{
"sts:AssumeRole",
},
},
},
}, nil);
if err != nil {
return err
}
ecsEvents, err := iam.NewRole(ctx, "ecs_events", &iam.RoleArgs{
Name: pulumi.String("ecs_events"),
AssumeRolePolicy: pulumi.String(assumeRole.Json),
})
if err != nil {
return err
}
ecsEventsRunTaskWithAnyRole, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
Statements: []iam.GetPolicyDocumentStatement{
{
Effect: pulumi.StringRef("Allow"),
Actions: []string{
"iam:PassRole",
},
Resources: []string{
"*",
},
},
{
Effect: pulumi.StringRef("Allow"),
Actions: []string{
"ecs:RunTask",
},
Resources: interface{}{
std.Replace(ctx, {
Text: taskName.Arn,
Search: "/:\\d+$/",
Replace: ":*",
}, nil).Result,
},
},
},
}, nil);
if err != nil {
return err
}
_, err = iam.NewRolePolicy(ctx, "ecs_events_run_task_with_any_role", &iam.RolePolicyArgs{
Name: pulumi.String("ecs_events_run_task_with_any_role"),
Role: ecsEvents.ID(),
Policy: pulumi.String(ecsEventsRunTaskWithAnyRole.Json),
})
if err != nil {
return err
}
tmpJSON0, err := json.Marshal(map[string]interface{}{
"containerOverrides": []map[string]interface{}{
map[string]interface{}{
"name": "name-of-container-to-override",
"command": []string{
"bin/console",
"scheduled-task",
},
},
},
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
_, err = cloudwatch.NewEventTarget(ctx, "ecs_scheduled_task", &cloudwatch.EventTargetArgs{
TargetId: pulumi.String("run-scheduled-task-every-hour"),
Arn: pulumi.Any(clusterName.Arn),
Rule: pulumi.Any(everyHour.Name),
RoleArn: ecsEvents.Arn,
EcsTarget: &cloudwatch.EventTargetEcsTargetArgs{
TaskCount: pulumi.Int(1),
TaskDefinitionArn: pulumi.Any(taskName.Arn),
},
Input: pulumi.String(json0),
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;

return await Deployment.RunAsync(() => 
{
    var assumeRole = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "Service",
                        Identifiers = new[]
                        {
                            "events.amazonaws.com",
                        },
                    },
                },
                Actions = new[]
                {
                    "sts:AssumeRole",
                },
            },
        },
    });

    var ecsEvents = new Aws.Iam.Role("ecs_events", new()
    {
        Name = "ecs_events",
        AssumeRolePolicy = assumeRole.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var ecsEventsRunTaskWithAnyRole = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Actions = new[]
                {
                    "iam:PassRole",
                },
                Resources = new[]
                {
                    "*",
                },
            },
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Actions = new[]
                {
                    "ecs:RunTask",
                },
                Resources = new[]
                {
                    Std.Replace.Invoke(new()
                    {
                        Text = taskName.Arn,
                        Search = "/:\\d+$/",
                        Replace = ":*",
                    }).Result,
                },
            },
        },
    });

    var ecsEventsRunTaskWithAnyRoleRolePolicy = new Aws.Iam.RolePolicy("ecs_events_run_task_with_any_role", new()
    {
        Name = "ecs_events_run_task_with_any_role",
        Role = ecsEvents.Id,
        Policy = ecsEventsRunTaskWithAnyRole.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var ecsScheduledTask = new Aws.CloudWatch.EventTarget("ecs_scheduled_task", new()
    {
        TargetId = "run-scheduled-task-every-hour",
        Arn = clusterName.Arn,
        Rule = everyHour.Name,
        RoleArn = ecsEvents.Arn,
        EcsTarget = new Aws.CloudWatch.Inputs.EventTargetEcsTargetArgs
        {
            TaskCount = 1,
            TaskDefinitionArn = taskName.Arn,
        },
        Input = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["containerOverrides"] = new[]
            {
                new Dictionary<string, object?>
                {
                    ["name"] = "name-of-container-to-override",
                    ["command"] = new[]
                    {
                        "bin/console",
                        "scheduled-task",
                    },
                },
            },
        }),
    });

});
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.iam.Role;
import com.pulumi.aws.iam.RoleArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.ReplaceArgs;
import com.pulumi.aws.iam.RolePolicy;
import com.pulumi.aws.iam.RolePolicyArgs;
import com.pulumi.aws.cloudwatch.EventTarget;
import com.pulumi.aws.cloudwatch.EventTargetArgs;
import com.pulumi.aws.cloudwatch.inputs.EventTargetEcsTargetArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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 assumeRole = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(GetPolicyDocumentStatementArgs.builder()
                .effect("Allow")
                .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                    .type("Service")
                    .identifiers("events.amazonaws.com")
                    .build())
                .actions("sts:AssumeRole")
                .build())
            .build());

        var ecsEvents = new Role("ecsEvents", RoleArgs.builder()
            .name("ecs_events")
            .assumeRolePolicy(assumeRole.json())
            .build());

        final var ecsEventsRunTaskWithAnyRole = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(            
                GetPolicyDocumentStatementArgs.builder()
                    .effect("Allow")
                    .actions("iam:PassRole")
                    .resources("*")
                    .build(),
                GetPolicyDocumentStatementArgs.builder()
                    .effect("Allow")
                    .actions("ecs:RunTask")
                    .resources(StdFunctions.replace(ReplaceArgs.builder()
                        .text(taskName.arn())
                        .search("/:\\d+$/")
                        .replace(":*")
                        .build()).result())
                    .build())
            .build());

        var ecsEventsRunTaskWithAnyRoleRolePolicy = new RolePolicy("ecsEventsRunTaskWithAnyRoleRolePolicy", RolePolicyArgs.builder()
            .name("ecs_events_run_task_with_any_role")
            .role(ecsEvents.id())
            .policy(ecsEventsRunTaskWithAnyRole.json())
            .build());

        var ecsScheduledTask = new EventTarget("ecsScheduledTask", EventTargetArgs.builder()
            .targetId("run-scheduled-task-every-hour")
            .arn(clusterName.arn())
            .rule(everyHour.name())
            .roleArn(ecsEvents.arn())
            .ecsTarget(EventTargetEcsTargetArgs.builder()
                .taskCount(1)
                .taskDefinitionArn(taskName.arn())
                .build())
            .input(serializeJson(
                jsonObject(
                    jsonProperty("containerOverrides", jsonArray(jsonObject(
                        jsonProperty("name", "name-of-container-to-override"),
                        jsonProperty("command", jsonArray(
                            "bin/console", 
                            "scheduled-task"
                        ))
                    )))
                )))
            .build());

    }
}
resources:
  ecsEvents:
    type: aws:iam:Role
    name: ecs_events
    properties:
      name: ecs_events
      assumeRolePolicy: ${assumeRole.json}
  ecsEventsRunTaskWithAnyRoleRolePolicy:
    type: aws:iam:RolePolicy
    name: ecs_events_run_task_with_any_role
    properties:
      name: ecs_events_run_task_with_any_role
      role: ${ecsEvents.id}
      policy: ${ecsEventsRunTaskWithAnyRole.json}
  ecsScheduledTask:
    type: aws:cloudwatch:EventTarget
    name: ecs_scheduled_task
    properties:
      targetId: run-scheduled-task-every-hour
      arn: ${clusterName.arn}
      rule: ${everyHour.name}
      roleArn: ${ecsEvents.arn}
      ecsTarget:
        taskCount: 1
        taskDefinitionArn: ${taskName.arn}
      input:
        fn::toJSON:
          containerOverrides:
            - name: name-of-container-to-override
              command:
                - bin/console
                - scheduled-task
variables:
  assumeRole:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            principals:
              - type: Service
                identifiers:
                  - events.amazonaws.com
            actions:
              - sts:AssumeRole
  ecsEventsRunTaskWithAnyRole:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            actions:
              - iam:PassRole
            resources:
              - '*'
          - effect: Allow
            actions:
              - ecs:RunTask
            resources:
              - fn::invoke:
                  function: std:replace
                  arguments:
                    text: ${taskName.arn}
                    search: /:\d+$/
                    replace: :*
                  return: result

The ecsTarget block specifies the task definition and count. The input property provides containerOverrides that replace the default command with custom arguments. EventBridge launches tasks in the cluster specified by arn, using the roleArn to pass IAM permissions to the task.

Invoke API Gateway endpoints from events

EventBridge can trigger API Gateway REST endpoints directly, passing event data as query parameters or headers.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const exampleEventRule = new aws.cloudwatch.EventRule("example", {});
const exampleDeployment = new aws.apigateway.Deployment("example", {restApi: exampleAwsApiGatewayRestApi.id});
const exampleStage = new aws.apigateway.Stage("example", {
    restApi: exampleAwsApiGatewayRestApi.id,
    deployment: exampleDeployment.id,
});
const example = new aws.cloudwatch.EventTarget("example", {
    arn: pulumi.interpolate`${exampleStage.executionArn}/GET`,
    rule: exampleEventRule.id,
    httpTarget: {
        queryStringParameters: {
            Body: "$.detail.body",
        },
        headerParameters: {
            Env: "Test",
        },
    },
});
import pulumi
import pulumi_aws as aws

example_event_rule = aws.cloudwatch.EventRule("example")
example_deployment = aws.apigateway.Deployment("example", rest_api=example_aws_api_gateway_rest_api["id"])
example_stage = aws.apigateway.Stage("example",
    rest_api=example_aws_api_gateway_rest_api["id"],
    deployment=example_deployment.id)
example = aws.cloudwatch.EventTarget("example",
    arn=example_stage.execution_arn.apply(lambda execution_arn: f"{execution_arn}/GET"),
    rule=example_event_rule.id,
    http_target={
        "query_string_parameters": {
            "Body": "$.detail.body",
        },
        "header_parameters": {
            "Env": "Test",
        },
    })
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apigateway"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudwatch"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		exampleEventRule, err := cloudwatch.NewEventRule(ctx, "example", nil)
		if err != nil {
			return err
		}
		exampleDeployment, err := apigateway.NewDeployment(ctx, "example", &apigateway.DeploymentArgs{
			RestApi: pulumi.Any(exampleAwsApiGatewayRestApi.Id),
		})
		if err != nil {
			return err
		}
		exampleStage, err := apigateway.NewStage(ctx, "example", &apigateway.StageArgs{
			RestApi:    pulumi.Any(exampleAwsApiGatewayRestApi.Id),
			Deployment: exampleDeployment.ID(),
		})
		if err != nil {
			return err
		}
		_, err = cloudwatch.NewEventTarget(ctx, "example", &cloudwatch.EventTargetArgs{
			Arn: exampleStage.ExecutionArn.ApplyT(func(executionArn string) (string, error) {
				return fmt.Sprintf("%v/GET", executionArn), nil
			}).(pulumi.StringOutput),
			Rule: exampleEventRule.ID(),
			HttpTarget: &cloudwatch.EventTargetHttpTargetArgs{
				QueryStringParameters: pulumi.StringMap{
					"Body": pulumi.String("$.detail.body"),
				},
				HeaderParameters: pulumi.StringMap{
					"Env": pulumi.String("Test"),
				},
			},
		})
		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 exampleEventRule = new Aws.CloudWatch.EventRule("example");

    var exampleDeployment = new Aws.ApiGateway.Deployment("example", new()
    {
        RestApi = exampleAwsApiGatewayRestApi.Id,
    });

    var exampleStage = new Aws.ApiGateway.Stage("example", new()
    {
        RestApi = exampleAwsApiGatewayRestApi.Id,
        Deployment = exampleDeployment.Id,
    });

    var example = new Aws.CloudWatch.EventTarget("example", new()
    {
        Arn = exampleStage.ExecutionArn.Apply(executionArn => $"{executionArn}/GET"),
        Rule = exampleEventRule.Id,
        HttpTarget = new Aws.CloudWatch.Inputs.EventTargetHttpTargetArgs
        {
            QueryStringParameters = 
            {
                { "Body", "$.detail.body" },
            },
            HeaderParameters = 
            {
                { "Env", "Test" },
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.cloudwatch.EventRule;
import com.pulumi.aws.apigateway.Deployment;
import com.pulumi.aws.apigateway.DeploymentArgs;
import com.pulumi.aws.apigateway.Stage;
import com.pulumi.aws.apigateway.StageArgs;
import com.pulumi.aws.cloudwatch.EventTarget;
import com.pulumi.aws.cloudwatch.EventTargetArgs;
import com.pulumi.aws.cloudwatch.inputs.EventTargetHttpTargetArgs;
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) {
        var exampleEventRule = new EventRule("exampleEventRule");

        var exampleDeployment = new Deployment("exampleDeployment", DeploymentArgs.builder()
            .restApi(exampleAwsApiGatewayRestApi.id())
            .build());

        var exampleStage = new Stage("exampleStage", StageArgs.builder()
            .restApi(exampleAwsApiGatewayRestApi.id())
            .deployment(exampleDeployment.id())
            .build());

        var example = new EventTarget("example", EventTargetArgs.builder()
            .arn(exampleStage.executionArn().applyValue(_executionArn -> String.format("%s/GET", _executionArn)))
            .rule(exampleEventRule.id())
            .httpTarget(EventTargetHttpTargetArgs.builder()
                .queryStringParameters(Map.of("Body", "$.detail.body"))
                .headerParameters(Map.of("Env", "Test"))
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:cloudwatch:EventTarget
    properties:
      arn: ${exampleStage.executionArn}/GET
      rule: ${exampleEventRule.id}
      httpTarget:
        queryStringParameters:
          Body: $.detail.body
        headerParameters:
          Env: Test
  exampleEventRule:
    type: aws:cloudwatch:EventRule
    name: example
  exampleDeployment:
    type: aws:apigateway:Deployment
    name: example
    properties:
      restApi: ${exampleAwsApiGatewayRestApi.id}
  exampleStage:
    type: aws:apigateway:Stage
    name: example
    properties:
      restApi: ${exampleAwsApiGatewayRestApi.id}
      deployment: ${exampleDeployment.id}

The httpTarget block maps event fields to query strings and headers. The queryStringParameters extract data from the event using JSONPath ($.detail.body), while headerParameters set static values. The arn points to the API Gateway stage execution endpoint.

Forward events to another account’s event bus

Multi-account architectures centralize event processing by forwarding events from workload accounts to a central monitoring account.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const assumeRole = aws.iam.getPolicyDocument({
    statements: [{
        effect: "Allow",
        principals: [{
            type: "Service",
            identifiers: ["events.amazonaws.com"],
        }],
        actions: ["sts:AssumeRole"],
    }],
});
const eventBusInvokeRemoteEventBusRole = new aws.iam.Role("event_bus_invoke_remote_event_bus", {
    name: "event-bus-invoke-remote-event-bus",
    assumeRolePolicy: assumeRole.then(assumeRole => assumeRole.json),
});
const eventBusInvokeRemoteEventBus = aws.iam.getPolicyDocument({
    statements: [{
        effect: "Allow",
        actions: ["events:PutEvents"],
        resources: ["arn:aws:events:eu-west-1:1234567890:event-bus/My-Event-Bus"],
    }],
});
const eventBusInvokeRemoteEventBusPolicy = new aws.iam.Policy("event_bus_invoke_remote_event_bus", {
    name: "event_bus_invoke_remote_event_bus",
    policy: eventBusInvokeRemoteEventBus.then(eventBusInvokeRemoteEventBus => eventBusInvokeRemoteEventBus.json),
});
const eventBusInvokeRemoteEventBusRolePolicyAttachment = new aws.iam.RolePolicyAttachment("event_bus_invoke_remote_event_bus", {
    role: eventBusInvokeRemoteEventBusRole.name,
    policyArn: eventBusInvokeRemoteEventBusPolicy.arn,
});
const stopInstances = new aws.cloudwatch.EventRule("stop_instances", {
    name: "StopInstance",
    description: "Stop instances nightly",
    scheduleExpression: "cron(0 0 * * ? *)",
});
const stopInstancesEventTarget = new aws.cloudwatch.EventTarget("stop_instances", {
    targetId: "StopInstance",
    arn: "arn:aws:events:eu-west-1:1234567890:event-bus/My-Event-Bus",
    rule: stopInstances.name,
    roleArn: eventBusInvokeRemoteEventBusRole.arn,
});
import pulumi
import pulumi_aws as aws

assume_role = aws.iam.get_policy_document(statements=[{
    "effect": "Allow",
    "principals": [{
        "type": "Service",
        "identifiers": ["events.amazonaws.com"],
    }],
    "actions": ["sts:AssumeRole"],
}])
event_bus_invoke_remote_event_bus_role = aws.iam.Role("event_bus_invoke_remote_event_bus",
    name="event-bus-invoke-remote-event-bus",
    assume_role_policy=assume_role.json)
event_bus_invoke_remote_event_bus = aws.iam.get_policy_document(statements=[{
    "effect": "Allow",
    "actions": ["events:PutEvents"],
    "resources": ["arn:aws:events:eu-west-1:1234567890:event-bus/My-Event-Bus"],
}])
event_bus_invoke_remote_event_bus_policy = aws.iam.Policy("event_bus_invoke_remote_event_bus",
    name="event_bus_invoke_remote_event_bus",
    policy=event_bus_invoke_remote_event_bus.json)
event_bus_invoke_remote_event_bus_role_policy_attachment = aws.iam.RolePolicyAttachment("event_bus_invoke_remote_event_bus",
    role=event_bus_invoke_remote_event_bus_role.name,
    policy_arn=event_bus_invoke_remote_event_bus_policy.arn)
stop_instances = aws.cloudwatch.EventRule("stop_instances",
    name="StopInstance",
    description="Stop instances nightly",
    schedule_expression="cron(0 0 * * ? *)")
stop_instances_event_target = aws.cloudwatch.EventTarget("stop_instances",
    target_id="StopInstance",
    arn="arn:aws:events:eu-west-1:1234567890:event-bus/My-Event-Bus",
    rule=stop_instances.name,
    role_arn=event_bus_invoke_remote_event_bus_role.arn)
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 {
		assumeRole, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Effect: pulumi.StringRef("Allow"),
					Principals: []iam.GetPolicyDocumentStatementPrincipal{
						{
							Type: "Service",
							Identifiers: []string{
								"events.amazonaws.com",
							},
						},
					},
					Actions: []string{
						"sts:AssumeRole",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		eventBusInvokeRemoteEventBusRole, err := iam.NewRole(ctx, "event_bus_invoke_remote_event_bus", &iam.RoleArgs{
			Name:             pulumi.String("event-bus-invoke-remote-event-bus"),
			AssumeRolePolicy: pulumi.String(assumeRole.Json),
		})
		if err != nil {
			return err
		}
		eventBusInvokeRemoteEventBus, err := iam.GetPolicyDocument(ctx, &iam.GetPolicyDocumentArgs{
			Statements: []iam.GetPolicyDocumentStatement{
				{
					Effect: pulumi.StringRef("Allow"),
					Actions: []string{
						"events:PutEvents",
					},
					Resources: []string{
						"arn:aws:events:eu-west-1:1234567890:event-bus/My-Event-Bus",
					},
				},
			},
		}, nil)
		if err != nil {
			return err
		}
		eventBusInvokeRemoteEventBusPolicy, err := iam.NewPolicy(ctx, "event_bus_invoke_remote_event_bus", &iam.PolicyArgs{
			Name:   pulumi.String("event_bus_invoke_remote_event_bus"),
			Policy: pulumi.String(eventBusInvokeRemoteEventBus.Json),
		})
		if err != nil {
			return err
		}
		_, err = iam.NewRolePolicyAttachment(ctx, "event_bus_invoke_remote_event_bus", &iam.RolePolicyAttachmentArgs{
			Role:      eventBusInvokeRemoteEventBusRole.Name,
			PolicyArn: eventBusInvokeRemoteEventBusPolicy.Arn,
		})
		if err != nil {
			return err
		}
		stopInstances, err := cloudwatch.NewEventRule(ctx, "stop_instances", &cloudwatch.EventRuleArgs{
			Name:               pulumi.String("StopInstance"),
			Description:        pulumi.String("Stop instances nightly"),
			ScheduleExpression: pulumi.String("cron(0 0 * * ? *)"),
		})
		if err != nil {
			return err
		}
		_, err = cloudwatch.NewEventTarget(ctx, "stop_instances", &cloudwatch.EventTargetArgs{
			TargetId: pulumi.String("StopInstance"),
			Arn:      pulumi.String("arn:aws:events:eu-west-1:1234567890:event-bus/My-Event-Bus"),
			Rule:     stopInstances.Name,
			RoleArn:  eventBusInvokeRemoteEventBusRole.Arn,
		})
		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 assumeRole = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "Service",
                        Identifiers = new[]
                        {
                            "events.amazonaws.com",
                        },
                    },
                },
                Actions = new[]
                {
                    "sts:AssumeRole",
                },
            },
        },
    });

    var eventBusInvokeRemoteEventBusRole = new Aws.Iam.Role("event_bus_invoke_remote_event_bus", new()
    {
        Name = "event-bus-invoke-remote-event-bus",
        AssumeRolePolicy = assumeRole.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var eventBusInvokeRemoteEventBus = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Actions = new[]
                {
                    "events:PutEvents",
                },
                Resources = new[]
                {
                    "arn:aws:events:eu-west-1:1234567890:event-bus/My-Event-Bus",
                },
            },
        },
    });

    var eventBusInvokeRemoteEventBusPolicy = new Aws.Iam.Policy("event_bus_invoke_remote_event_bus", new()
    {
        Name = "event_bus_invoke_remote_event_bus",
        PolicyDocument = eventBusInvokeRemoteEventBus.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
    });

    var eventBusInvokeRemoteEventBusRolePolicyAttachment = new Aws.Iam.RolePolicyAttachment("event_bus_invoke_remote_event_bus", new()
    {
        Role = eventBusInvokeRemoteEventBusRole.Name,
        PolicyArn = eventBusInvokeRemoteEventBusPolicy.Arn,
    });

    var stopInstances = new Aws.CloudWatch.EventRule("stop_instances", new()
    {
        Name = "StopInstance",
        Description = "Stop instances nightly",
        ScheduleExpression = "cron(0 0 * * ? *)",
    });

    var stopInstancesEventTarget = new Aws.CloudWatch.EventTarget("stop_instances", new()
    {
        TargetId = "StopInstance",
        Arn = "arn:aws:events:eu-west-1:1234567890:event-bus/My-Event-Bus",
        Rule = stopInstances.Name,
        RoleArn = eventBusInvokeRemoteEventBusRole.Arn,
    });

});
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.iam.Role;
import com.pulumi.aws.iam.RoleArgs;
import com.pulumi.aws.iam.Policy;
import com.pulumi.aws.iam.PolicyArgs;
import com.pulumi.aws.iam.RolePolicyAttachment;
import com.pulumi.aws.iam.RolePolicyAttachmentArgs;
import com.pulumi.aws.cloudwatch.EventRule;
import com.pulumi.aws.cloudwatch.EventRuleArgs;
import com.pulumi.aws.cloudwatch.EventTarget;
import com.pulumi.aws.cloudwatch.EventTargetArgs;
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 assumeRole = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(GetPolicyDocumentStatementArgs.builder()
                .effect("Allow")
                .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                    .type("Service")
                    .identifiers("events.amazonaws.com")
                    .build())
                .actions("sts:AssumeRole")
                .build())
            .build());

        var eventBusInvokeRemoteEventBusRole = new Role("eventBusInvokeRemoteEventBusRole", RoleArgs.builder()
            .name("event-bus-invoke-remote-event-bus")
            .assumeRolePolicy(assumeRole.json())
            .build());

        final var eventBusInvokeRemoteEventBus = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(GetPolicyDocumentStatementArgs.builder()
                .effect("Allow")
                .actions("events:PutEvents")
                .resources("arn:aws:events:eu-west-1:1234567890:event-bus/My-Event-Bus")
                .build())
            .build());

        var eventBusInvokeRemoteEventBusPolicy = new Policy("eventBusInvokeRemoteEventBusPolicy", PolicyArgs.builder()
            .name("event_bus_invoke_remote_event_bus")
            .policy(eventBusInvokeRemoteEventBus.json())
            .build());

        var eventBusInvokeRemoteEventBusRolePolicyAttachment = new RolePolicyAttachment("eventBusInvokeRemoteEventBusRolePolicyAttachment", RolePolicyAttachmentArgs.builder()
            .role(eventBusInvokeRemoteEventBusRole.name())
            .policyArn(eventBusInvokeRemoteEventBusPolicy.arn())
            .build());

        var stopInstances = new EventRule("stopInstances", EventRuleArgs.builder()
            .name("StopInstance")
            .description("Stop instances nightly")
            .scheduleExpression("cron(0 0 * * ? *)")
            .build());

        var stopInstancesEventTarget = new EventTarget("stopInstancesEventTarget", EventTargetArgs.builder()
            .targetId("StopInstance")
            .arn("arn:aws:events:eu-west-1:1234567890:event-bus/My-Event-Bus")
            .rule(stopInstances.name())
            .roleArn(eventBusInvokeRemoteEventBusRole.arn())
            .build());

    }
}
resources:
  eventBusInvokeRemoteEventBusRole:
    type: aws:iam:Role
    name: event_bus_invoke_remote_event_bus
    properties:
      name: event-bus-invoke-remote-event-bus
      assumeRolePolicy: ${assumeRole.json}
  eventBusInvokeRemoteEventBusPolicy:
    type: aws:iam:Policy
    name: event_bus_invoke_remote_event_bus
    properties:
      name: event_bus_invoke_remote_event_bus
      policy: ${eventBusInvokeRemoteEventBus.json}
  eventBusInvokeRemoteEventBusRolePolicyAttachment:
    type: aws:iam:RolePolicyAttachment
    name: event_bus_invoke_remote_event_bus
    properties:
      role: ${eventBusInvokeRemoteEventBusRole.name}
      policyArn: ${eventBusInvokeRemoteEventBusPolicy.arn}
  stopInstances:
    type: aws:cloudwatch:EventRule
    name: stop_instances
    properties:
      name: StopInstance
      description: Stop instances nightly
      scheduleExpression: cron(0 0 * * ? *)
  stopInstancesEventTarget:
    type: aws:cloudwatch:EventTarget
    name: stop_instances
    properties:
      targetId: StopInstance
      arn: arn:aws:events:eu-west-1:1234567890:event-bus/My-Event-Bus
      rule: ${stopInstances.name}
      roleArn: ${eventBusInvokeRemoteEventBusRole.arn}
variables:
  assumeRole:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            principals:
              - type: Service
                identifiers:
                  - events.amazonaws.com
            actions:
              - sts:AssumeRole
  eventBusInvokeRemoteEventBus:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            actions:
              - events:PutEvents
            resources:
              - arn:aws:events:eu-west-1:1234567890:event-bus/My-Event-Bus

The arn property specifies the target event bus in another account. The roleArn grants PutEvents permissions to the remote bus. The target account must configure its event bus policy to accept events from the source account.

Transform event data into custom JSON payloads

Targets often need event data in a different structure than EventBridge provides. Input transformers extract and reshape fields.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const exampleEventRule = new aws.cloudwatch.EventRule("example", {});
const example = new aws.cloudwatch.EventTarget("example", {
    arn: exampleAwsLambdaFunction.arn,
    rule: exampleEventRule.id,
    inputTransformer: {
        inputPaths: {
            instance: "$.detail.instance",
            status: "$.detail.status",
        },
        inputTemplate: `{
  \\"instance_id\\": <instance>,
  \\"instance_status\\": <status>
}
`,
    },
});
import pulumi
import pulumi_aws as aws

example_event_rule = aws.cloudwatch.EventRule("example")
example = aws.cloudwatch.EventTarget("example",
    arn=example_aws_lambda_function["arn"],
    rule=example_event_rule.id,
    input_transformer={
        "input_paths": {
            "instance": "$.detail.instance",
            "status": "$.detail.status",
        },
        "input_template": """{
  \"instance_id\": <instance>,
  \"instance_status\": <status>
}
""",
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudwatch"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		exampleEventRule, err := cloudwatch.NewEventRule(ctx, "example", nil)
		if err != nil {
			return err
		}
		_, err = cloudwatch.NewEventTarget(ctx, "example", &cloudwatch.EventTargetArgs{
			Arn:  pulumi.Any(exampleAwsLambdaFunction.Arn),
			Rule: exampleEventRule.ID(),
			InputTransformer: &cloudwatch.EventTargetInputTransformerArgs{
				InputPaths: pulumi.StringMap{
					"instance": pulumi.String("$.detail.instance"),
					"status":   pulumi.String("$.detail.status"),
				},
				InputTemplate: pulumi.String("{\n  \\\"instance_id\\\": <instance>,\n  \\\"instance_status\\\": <status>\n}\n"),
			},
		})
		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 exampleEventRule = new Aws.CloudWatch.EventRule("example");

    var example = new Aws.CloudWatch.EventTarget("example", new()
    {
        Arn = exampleAwsLambdaFunction.Arn,
        Rule = exampleEventRule.Id,
        InputTransformer = new Aws.CloudWatch.Inputs.EventTargetInputTransformerArgs
        {
            InputPaths = 
            {
                { "instance", "$.detail.instance" },
                { "status", "$.detail.status" },
            },
            InputTemplate = @"{
  \""instance_id\"": <instance>,
  \""instance_status\"": <status>
}
",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.cloudwatch.EventRule;
import com.pulumi.aws.cloudwatch.EventTarget;
import com.pulumi.aws.cloudwatch.EventTargetArgs;
import com.pulumi.aws.cloudwatch.inputs.EventTargetInputTransformerArgs;
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) {
        var exampleEventRule = new EventRule("exampleEventRule");

        var example = new EventTarget("example", EventTargetArgs.builder()
            .arn(exampleAwsLambdaFunction.arn())
            .rule(exampleEventRule.id())
            .inputTransformer(EventTargetInputTransformerArgs.builder()
                .inputPaths(Map.ofEntries(
                    Map.entry("instance", "$.detail.instance"),
                    Map.entry("status", "$.detail.status")
                ))
                .inputTemplate("""
{
  \"instance_id\": <instance>,
  \"instance_status\": <status>
}
                """)
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:cloudwatch:EventTarget
    properties:
      arn: ${exampleAwsLambdaFunction.arn}
      rule: ${exampleEventRule.id}
      inputTransformer:
        inputPaths:
          instance: $.detail.instance
          status: $.detail.status
        inputTemplate: |
          {
            \"instance_id\": <instance>,
            \"instance_status\": <status>
          }          
  exampleEventRule:
    type: aws:cloudwatch:EventRule
    name: example

The inputTransformer block defines inputPaths that extract fields from the event using JSONPath expressions. The inputTemplate constructs a new JSON object using those extracted values (referenced as and ). This transformed payload is what the target receives.

Send events to CloudWatch Logs for auditing

Security and compliance workflows archive EventBridge events to CloudWatch Logs for long-term retention.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.cloudwatch.LogGroup("example", {
    name: "/aws/events/guardduty/logs",
    retentionInDays: 1,
});
const exampleEventRule = new aws.cloudwatch.EventRule("example", {
    name: "guard-duty_event_rule",
    description: "GuardDuty Findings",
    eventPattern: JSON.stringify({
        source: ["aws.guardduty"],
    }),
    tags: {
        Environment: "example",
    },
});
const exampleLogPolicy = aws.iam.getPolicyDocumentOutput({
    statements: [
        {
            effect: "Allow",
            actions: ["logs:CreateLogStream"],
            resources: [pulumi.interpolate`${example.arn}:*`],
            principals: [{
                type: "Service",
                identifiers: [
                    "events.amazonaws.com",
                    "delivery.logs.amazonaws.com",
                ],
            }],
        },
        {
            effect: "Allow",
            actions: ["logs:PutLogEvents"],
            resources: [pulumi.interpolate`${example.arn}:*:*`],
            principals: [{
                type: "Service",
                identifiers: [
                    "events.amazonaws.com",
                    "delivery.logs.amazonaws.com",
                ],
            }],
            conditions: [{
                test: "ArnEquals",
                values: [exampleEventRule.arn],
                variable: "aws:SourceArn",
            }],
        },
    ],
});
const exampleLogResourcePolicy = new aws.cloudwatch.LogResourcePolicy("example", {
    policyDocument: exampleLogPolicy.apply(exampleLogPolicy => exampleLogPolicy.json),
    policyName: "guardduty-log-publishing-policy",
});
const exampleEventTarget = new aws.cloudwatch.EventTarget("example", {
    rule: exampleEventRule.name,
    arn: example.arn,
});
import pulumi
import json
import pulumi_aws as aws

example = aws.cloudwatch.LogGroup("example",
    name="/aws/events/guardduty/logs",
    retention_in_days=1)
example_event_rule = aws.cloudwatch.EventRule("example",
    name="guard-duty_event_rule",
    description="GuardDuty Findings",
    event_pattern=json.dumps({
        "source": ["aws.guardduty"],
    }),
    tags={
        "Environment": "example",
    })
example_log_policy = aws.iam.get_policy_document_output(statements=[
    {
        "effect": "Allow",
        "actions": ["logs:CreateLogStream"],
        "resources": [example.arn.apply(lambda arn: f"{arn}:*")],
        "principals": [{
            "type": "Service",
            "identifiers": [
                "events.amazonaws.com",
                "delivery.logs.amazonaws.com",
            ],
        }],
    },
    {
        "effect": "Allow",
        "actions": ["logs:PutLogEvents"],
        "resources": [example.arn.apply(lambda arn: f"{arn}:*:*")],
        "principals": [{
            "type": "Service",
            "identifiers": [
                "events.amazonaws.com",
                "delivery.logs.amazonaws.com",
            ],
        }],
        "conditions": [{
            "test": "ArnEquals",
            "values": [example_event_rule.arn],
            "variable": "aws:SourceArn",
        }],
    },
])
example_log_resource_policy = aws.cloudwatch.LogResourcePolicy("example",
    policy_document=example_log_policy.json,
    policy_name="guardduty-log-publishing-policy")
example_event_target = aws.cloudwatch.EventTarget("example",
    rule=example_event_rule.name,
    arn=example.arn)
package main

import (
	"encoding/json"
	"fmt"

	"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 {
		example, err := cloudwatch.NewLogGroup(ctx, "example", &cloudwatch.LogGroupArgs{
			Name:            pulumi.String("/aws/events/guardduty/logs"),
			RetentionInDays: pulumi.Int(1),
		})
		if err != nil {
			return err
		}
		tmpJSON0, err := json.Marshal(map[string]interface{}{
			"source": []string{
				"aws.guardduty",
			},
		})
		if err != nil {
			return err
		}
		json0 := string(tmpJSON0)
		exampleEventRule, err := cloudwatch.NewEventRule(ctx, "example", &cloudwatch.EventRuleArgs{
			Name:         pulumi.String("guard-duty_event_rule"),
			Description:  pulumi.String("GuardDuty Findings"),
			EventPattern: pulumi.String(json0),
			Tags: pulumi.StringMap{
				"Environment": pulumi.String("example"),
			},
		})
		if err != nil {
			return err
		}
		exampleLogPolicy := iam.GetPolicyDocumentOutput(ctx, iam.GetPolicyDocumentOutputArgs{
			Statements: iam.GetPolicyDocumentStatementArray{
				&iam.GetPolicyDocumentStatementArgs{
					Effect: pulumi.String("Allow"),
					Actions: pulumi.StringArray{
						pulumi.String("logs:CreateLogStream"),
					},
					Resources: pulumi.StringArray{
						example.Arn.ApplyT(func(arn string) (string, error) {
							return fmt.Sprintf("%v:*", arn), nil
						}).(pulumi.StringOutput),
					},
					Principals: iam.GetPolicyDocumentStatementPrincipalArray{
						&iam.GetPolicyDocumentStatementPrincipalArgs{
							Type: pulumi.String("Service"),
							Identifiers: pulumi.StringArray{
								pulumi.String("events.amazonaws.com"),
								pulumi.String("delivery.logs.amazonaws.com"),
							},
						},
					},
				},
				&iam.GetPolicyDocumentStatementArgs{
					Effect: pulumi.String("Allow"),
					Actions: pulumi.StringArray{
						pulumi.String("logs:PutLogEvents"),
					},
					Resources: pulumi.StringArray{
						example.Arn.ApplyT(func(arn string) (string, error) {
							return fmt.Sprintf("%v:*:*", arn), nil
						}).(pulumi.StringOutput),
					},
					Principals: iam.GetPolicyDocumentStatementPrincipalArray{
						&iam.GetPolicyDocumentStatementPrincipalArgs{
							Type: pulumi.String("Service"),
							Identifiers: pulumi.StringArray{
								pulumi.String("events.amazonaws.com"),
								pulumi.String("delivery.logs.amazonaws.com"),
							},
						},
					},
					Conditions: iam.GetPolicyDocumentStatementConditionArray{
						&iam.GetPolicyDocumentStatementConditionArgs{
							Test: pulumi.String("ArnEquals"),
							Values: pulumi.StringArray{
								exampleEventRule.Arn,
							},
							Variable: pulumi.String("aws:SourceArn"),
						},
					},
				},
			},
		}, nil)
		_, err = cloudwatch.NewLogResourcePolicy(ctx, "example", &cloudwatch.LogResourcePolicyArgs{
			PolicyDocument: pulumi.String(exampleLogPolicy.ApplyT(func(exampleLogPolicy iam.GetPolicyDocumentResult) (*string, error) {
				return &exampleLogPolicy.Json, nil
			}).(pulumi.StringPtrOutput)),
			PolicyName: pulumi.String("guardduty-log-publishing-policy"),
		})
		if err != nil {
			return err
		}
		_, err = cloudwatch.NewEventTarget(ctx, "example", &cloudwatch.EventTargetArgs{
			Rule: exampleEventRule.Name,
			Arn:  example.Arn,
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.CloudWatch.LogGroup("example", new()
    {
        Name = "/aws/events/guardduty/logs",
        RetentionInDays = 1,
    });

    var exampleEventRule = new Aws.CloudWatch.EventRule("example", new()
    {
        Name = "guard-duty_event_rule",
        Description = "GuardDuty Findings",
        EventPattern = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["source"] = new[]
            {
                "aws.guardduty",
            },
        }),
        Tags = 
        {
            { "Environment", "example" },
        },
    });

    var exampleLogPolicy = Aws.Iam.GetPolicyDocument.Invoke(new()
    {
        Statements = new[]
        {
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Actions = new[]
                {
                    "logs:CreateLogStream",
                },
                Resources = new[]
                {
                    $"{example.Arn}:*",
                },
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "Service",
                        Identifiers = new[]
                        {
                            "events.amazonaws.com",
                            "delivery.logs.amazonaws.com",
                        },
                    },
                },
            },
            new Aws.Iam.Inputs.GetPolicyDocumentStatementInputArgs
            {
                Effect = "Allow",
                Actions = new[]
                {
                    "logs:PutLogEvents",
                },
                Resources = new[]
                {
                    $"{example.Arn}:*:*",
                },
                Principals = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementPrincipalInputArgs
                    {
                        Type = "Service",
                        Identifiers = new[]
                        {
                            "events.amazonaws.com",
                            "delivery.logs.amazonaws.com",
                        },
                    },
                },
                Conditions = new[]
                {
                    new Aws.Iam.Inputs.GetPolicyDocumentStatementConditionInputArgs
                    {
                        Test = "ArnEquals",
                        Values = new[]
                        {
                            exampleEventRule.Arn,
                        },
                        Variable = "aws:SourceArn",
                    },
                },
            },
        },
    });

    var exampleLogResourcePolicy = new Aws.CloudWatch.LogResourcePolicy("example", new()
    {
        PolicyDocument = exampleLogPolicy.Apply(getPolicyDocumentResult => getPolicyDocumentResult.Json),
        PolicyName = "guardduty-log-publishing-policy",
    });

    var exampleEventTarget = new Aws.CloudWatch.EventTarget("example", new()
    {
        Rule = exampleEventRule.Name,
        Arn = example.Arn,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.cloudwatch.LogGroup;
import com.pulumi.aws.cloudwatch.LogGroupArgs;
import com.pulumi.aws.cloudwatch.EventRule;
import com.pulumi.aws.cloudwatch.EventRuleArgs;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.cloudwatch.LogResourcePolicy;
import com.pulumi.aws.cloudwatch.LogResourcePolicyArgs;
import com.pulumi.aws.cloudwatch.EventTarget;
import com.pulumi.aws.cloudwatch.EventTargetArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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) {
        var example = new LogGroup("example", LogGroupArgs.builder()
            .name("/aws/events/guardduty/logs")
            .retentionInDays(1)
            .build());

        var exampleEventRule = new EventRule("exampleEventRule", EventRuleArgs.builder()
            .name("guard-duty_event_rule")
            .description("GuardDuty Findings")
            .eventPattern(serializeJson(
                jsonObject(
                    jsonProperty("source", jsonArray("aws.guardduty"))
                )))
            .tags(Map.of("Environment", "example"))
            .build());

        final var exampleLogPolicy = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
            .statements(            
                GetPolicyDocumentStatementArgs.builder()
                    .effect("Allow")
                    .actions("logs:CreateLogStream")
                    .resources(example.arn().applyValue(_arn -> String.format("%s:*", _arn)))
                    .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                        .type("Service")
                        .identifiers(                        
                            "events.amazonaws.com",
                            "delivery.logs.amazonaws.com")
                        .build())
                    .build(),
                GetPolicyDocumentStatementArgs.builder()
                    .effect("Allow")
                    .actions("logs:PutLogEvents")
                    .resources(example.arn().applyValue(_arn -> String.format("%s:*:*", _arn)))
                    .principals(GetPolicyDocumentStatementPrincipalArgs.builder()
                        .type("Service")
                        .identifiers(                        
                            "events.amazonaws.com",
                            "delivery.logs.amazonaws.com")
                        .build())
                    .conditions(GetPolicyDocumentStatementConditionArgs.builder()
                        .test("ArnEquals")
                        .values(exampleEventRule.arn())
                        .variable("aws:SourceArn")
                        .build())
                    .build())
            .build());

        var exampleLogResourcePolicy = new LogResourcePolicy("exampleLogResourcePolicy", LogResourcePolicyArgs.builder()
            .policyDocument(exampleLogPolicy.applyValue(_exampleLogPolicy -> _exampleLogPolicy.json()))
            .policyName("guardduty-log-publishing-policy")
            .build());

        var exampleEventTarget = new EventTarget("exampleEventTarget", EventTargetArgs.builder()
            .rule(exampleEventRule.name())
            .arn(example.arn())
            .build());

    }
}
resources:
  example:
    type: aws:cloudwatch:LogGroup
    properties:
      name: /aws/events/guardduty/logs
      retentionInDays: 1
  exampleLogResourcePolicy:
    type: aws:cloudwatch:LogResourcePolicy
    name: example
    properties:
      policyDocument: ${exampleLogPolicy.json}
      policyName: guardduty-log-publishing-policy
  exampleEventRule:
    type: aws:cloudwatch:EventRule
    name: example
    properties:
      name: guard-duty_event_rule
      description: GuardDuty Findings
      eventPattern:
        fn::toJSON:
          source:
            - aws.guardduty
      tags:
        Environment: example
  exampleEventTarget:
    type: aws:cloudwatch:EventTarget
    name: example
    properties:
      rule: ${exampleEventRule.name}
      arn: ${example.arn}
variables:
  exampleLogPolicy:
    fn::invoke:
      function: aws:iam:getPolicyDocument
      arguments:
        statements:
          - effect: Allow
            actions:
              - logs:CreateLogStream
            resources:
              - ${example.arn}:*
            principals:
              - type: Service
                identifiers:
                  - events.amazonaws.com
                  - delivery.logs.amazonaws.com
          - effect: Allow
            actions:
              - logs:PutLogEvents
            resources:
              - ${example.arn}:*:*
            principals:
              - type: Service
                identifiers:
                  - events.amazonaws.com
                  - delivery.logs.amazonaws.com
            conditions:
              - test: ArnEquals
                values:
                  - ${exampleEventRule.arn}
                variable: aws:SourceArn

The arn property points to a CloudWatch log group. EventBridge writes events as log entries, but requires a resource policy (LogResourcePolicy) that grants CreateLogStream and PutLogEvents permissions. The policy conditions ensure only the specified rule can write to the log group.

Beyond these examples

These snippets focus on specific event target features: target types (Kinesis, ECS, API Gateway, SSM, event buses, CloudWatch Logs), input transformation and event data mapping, and IAM roles and cross-account routing. They’re intentionally minimal rather than full event-driven applications.

The examples reference pre-existing infrastructure such as EventBridge rules that trigger the targets, IAM roles with permissions for target services, and target resources (Kinesis streams, ECS clusters, API Gateway stages, SSM documents, log groups). They focus on configuring the target rather than provisioning everything around it.

To keep things focused, common target patterns are omitted, including:

  • Retry policies and dead letter queues (retryPolicy, deadLetterConfig)
  • Batch and SageMaker Pipeline targets
  • SQS and Redshift targets
  • Lambda permissions and SNS topic policies (required for those targets)

These omissions are intentional: the goal is to illustrate how each target type is wired, not provide drop-in event routing modules. See the EventBridge Target resource reference for all available configuration options.

Let's configure AWS EventBridge Targets

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Permissions & IAM
Why isn't my Lambda function or SNS topic being invoked by EventBridge?
Lambda functions and SNS topics require explicit permissions to be invoked by EventBridge rules. Configure aws.lambda.Permission for Lambda targets or aws.sns.TopicPolicy for SNS targets to grant EventBridge the necessary invoke permissions.
When do I need to specify a roleArn for my target?
You must provide roleArn when using ecsTarget, or when your target is an EC2 instance, Kinesis data stream, Step Functions state machine, or Event Bus in a different account or region. The role must have permissions to invoke the target service.
Configuration & Immutability
What properties can't I change after creating an EventBridge target?
The rule, targetId, and eventBusName properties are immutable and cannot be modified after creation. Changing these values requires replacing the entire target resource.
What happens if I don't specify an event bus name?
If you omit eventBusName, EventBridge uses the default event bus automatically.
What does forceDestroy do?
Setting forceDestroy to true allows deletion of managed rules created by AWS. It defaults to false.
Input Handling
Can I use input, inputPath, and inputTransformer together?
No, these three properties are mutually exclusive. You must choose only one method to pass data to your target: input for static JSON, inputPath for JSONPath extraction, or inputTransformer for custom transformations.
How do I transform event data before sending it to a target?
Use inputTransformer with inputPaths to extract specific fields from the event (e.g., instance: "$.detail.instance"), then format them in inputTemplate as either a JSON object or a simple string.
Target Types & Limits
How many targets or configurations can I specify?
Most target type configurations (like ecsTarget, batchTarget, httpTarget) allow a maximum of 1. However, runCommandTargets allows up to 5 entries for EC2 Run Command invocations.
How do I override container commands when triggering ECS tasks?
Use the input property with a JSON object containing containerOverrides. Specify the container name and a command array with your custom commands.
How do I invoke an API Gateway endpoint from EventBridge?
Set the target arn to your API Gateway stage execution ARN followed by the HTTP method (e.g., ${stage.executionArn}/GET). Use httpTarget to configure query string parameters and header parameters.
Cross-Account & Advanced Scenarios
How do I send events to an Event Bus in a different AWS account?
Create an IAM role with events:PutEvents permission for the target event bus ARN. Then configure your target with the cross-account event bus ARN and specify the role ARN in roleArn.
How do I send events to a CloudWatch Log Group?
Set the target arn to your log group ARN and create a aws.cloudwatch.LogResourcePolicy that grants logs:CreateLogStream and logs:PutLogEvents permissions to the EventBridge service principals.

Using a different cloud?

Explore integration guides for other cloud providers: