feat: first commit (#1)

This commit is contained in:
Sven Lito 2021-03-22 23:15:02 +07:00 committed by GitHub
parent da1b381697
commit 48eeb94c65
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 2733 additions and 1 deletions

111
.chglog/CHANGELOG.tpl.md Normal file
View file

@ -0,0 +1,111 @@
# Change Log
All notable changes to this project will be documented in this file.
{{ if .Versions -}}
<a name="unreleased"></a>
## [Unreleased]
{{ if .Unreleased.CommitGroups -}}
{{ range .Unreleased.CommitGroups -}}
### {{ .Title }}
{{ range .Commits -}}
{{/* SKIPPING RULES - START */ -}}
{{- if not (hasPrefix .Subject "Updated CHANGELOG") -}}
{{- if not (contains .Subject "[ci skip]") -}}
{{- if not (contains .Subject "[skip ci]") -}}
{{- if not (hasPrefix .Subject "Merge pull request ") -}}
{{- if not (hasPrefix .Subject "Added CHANGELOG") -}}
{{- /* SKIPPING RULES - END */ -}}
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
{{/* SKIPPING RULES - START */ -}}
{{ end -}}
{{ end -}}
{{ end -}}
{{ end -}}
{{ end -}}
{{/* SKIPPING RULES - END */ -}}
{{ end }}
{{ end -}}
{{ else }}
{{ range .Unreleased.Commits -}}
{{/* SKIPPING RULES - START */ -}}
{{- if not (hasPrefix .Subject "Updated CHANGELOG") -}}
{{- if not (contains .Subject "[ci skip]") -}}
{{- if not (contains .Subject "[skip ci]") -}}
{{- if not (hasPrefix .Subject "Merge pull request ") -}}
{{- if not (hasPrefix .Subject "Added CHANGELOG") -}}
{{- /* SKIPPING RULES - END */ -}}
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
{{/* SKIPPING RULES - START */ -}}
{{ end -}}
{{ end -}}
{{ end -}}
{{ end -}}
{{ end -}}
{{/* SKIPPING RULES - END */ -}}
{{ end }}
{{ end -}}
{{ end -}}
{{ range .Versions }}
<a name="{{ .Tag.Name }}"></a>
## {{ if .Tag.Previous }}[{{ .Tag.Name }}]{{ else }}{{ .Tag.Name }}{{ end }} - {{ datetime "2006-01-02" .Tag.Date }}
{{ if .CommitGroups -}}
{{ range .CommitGroups -}}
### {{ .Title }}
{{ range .Commits -}}
{{/* SKIPPING RULES - START */ -}}
{{- if not (hasPrefix .Subject "Updated CHANGELOG") -}}
{{- if not (contains .Subject "[ci skip]") -}}
{{- if not (contains .Subject "[skip ci]") -}}
{{- if not (hasPrefix .Subject "Merge pull request ") -}}
{{- if not (hasPrefix .Subject "Added CHANGELOG") -}}
{{- /* SKIPPING RULES - END */ -}}
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
{{/* SKIPPING RULES - START */ -}}
{{ end -}}
{{ end -}}
{{ end -}}
{{ end -}}
{{ end -}}
{{/* SKIPPING RULES - END */ -}}
{{ end }}
{{ end -}}
{{ else }}
{{ range .Commits -}}
{{/* SKIPPING RULES - START */ -}}
{{- if not (hasPrefix .Subject "Updated CHANGELOG") -}}
{{- if not (contains .Subject "[ci skip]") -}}
{{- if not (contains .Subject "[skip ci]") -}}
{{- if not (hasPrefix .Subject "Merge pull request ") -}}
{{- if not (hasPrefix .Subject "Added CHANGELOG") -}}
{{- /* SKIPPING RULES - END */ -}}
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ .Subject }}
{{/* SKIPPING RULES - START */ -}}
{{ end -}}
{{ end -}}
{{ end -}}
{{ end -}}
{{ end -}}
{{/* SKIPPING RULES - END */ -}}
{{ end }}
{{ end -}}
{{- if .NoteGroups -}}
{{ range .NoteGroups -}}
### {{ .Title }}
{{ range .Notes }}
{{ .Body }}
{{ end }}
{{ end -}}
{{ end -}}
{{ end -}}
{{- if .Versions }}
[Unreleased]: {{ .Info.RepositoryURL }}/compare/{{ $latest := index .Versions 0 }}{{ $latest.Tag.Name }}...HEAD
{{ range .Versions -}}
{{ if .Tag.Previous -}}
[{{ .Tag.Name }}]: {{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}
{{ end -}}
{{ end -}}
{{ end -}}

11
.chglog/config.yml Normal file
View file

@ -0,0 +1,11 @@
---
style: github
template: CHANGELOG.tpl.md
info:
title: CHANGELOG
repository_url: https://github.com/svenlito/terraform-aws-eventbridge
options:
header:
pattern: "^(.*)$"
pattern_maps:
- Subject

32
.editorconfig Normal file
View file

@ -0,0 +1,32 @@
# EditorConfig is awesome: http://EditorConfig.org
# Uses editorconfig to maintain consistent coding styles
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
max_line_length = 80
trim_trailing_whitespace = true
[*.{hcl}]
indent_size = 2
indent_style = space
[*.md]
max_line_length = 0
trim_trailing_whitespace = false
# Tab indentation (no size specified)
[Makefile]
tab_width = 2
indent_style = tab
# Don't wrap lines for Git commit messages
[COMMIT_EDITMSG]
max_line_length = 0

102
.github/workflows/pre-commit.yml vendored Normal file
View file

@ -0,0 +1,102 @@
---
name: Pre-Commit
on:
pull_request:
push:
branches:
- master
jobs:
# Min Terraform version(s)
getDirectories:
name: Get root directories
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Python
uses: actions/setup-python@v2
- name: Build matrix
id: matrix
run: |
DIRS=$(python -c "import json; import glob; print(json.dumps([x.replace('/versions.tf', '') for x in glob.glob('./**/versions.tf', recursive=True)]))")
echo "::set-output name=directories::$DIRS"
outputs:
directories: ${{ steps.matrix.outputs.directories }}
preCommitMinVersions:
name: Min TF validate
needs: getDirectories
runs-on: ubuntu-latest
strategy:
matrix:
directory: ${{ fromJson(needs.getDirectories.outputs.directories) }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Python
uses: actions/setup-python@v2
- name: Terraform min/max versions
id: minMax
uses: clowdhaus/terraform-min-max@v1.0.1
with:
directory: ${{ matrix.directory }}
- name: Install Terraform v${{ steps.minMax.outputs.minVersion }}
uses: hashicorp/setup-terraform@v1
with:
terraform_version: ${{ steps.minMax.outputs.minVersion }}
- name: Install pre-commit dependencies
run: pip install pre-commit
- name: Execute pre-commit
# Run only validate pre-commit check on min version supported
if: ${{ matrix.directory != '.' }}
run:
pre-commit run terraform_validate --color=always --show-diff-on-failure --files ${{ matrix.directory }}/*
- name: Execute pre-commit
# Run only validate pre-commit check on min version supported
if: ${{ matrix.directory == '.' }}
run:
pre-commit run terraform_validate --color=always --show-diff-on-failure --files $(ls *.tf)
# Max Terraform version
getBaseVersion:
name: Module max TF version
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Terraform min/max versions
id: minMax
uses: clowdhaus/terraform-min-max@v1.0.1
outputs:
minVersion: ${{ steps.minMax.outputs.minVersion }}
maxVersion: ${{ steps.minMax.outputs.maxVersion }}
preCommitMaxVersion:
name: Max TF pre-commit
runs-on: ubuntu-latest
needs: getBaseVersion
strategy:
fail-fast: false
matrix:
version:
- ${{ needs.getBaseVersion.outputs.maxVersion }}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Python
uses: actions/setup-python@v2
- name: Install Terraform v${{ matrix.version }}
uses: hashicorp/setup-terraform@v1
with:
terraform_version: ${{ matrix.version }}
- name: Install pre-commit dependencies
run: |
pip install pre-commit
curl -L "$(curl -s https://api.github.com/repos/terraform-docs/terraform-docs/releases/latest | grep -o -E "https://.+?-linux-amd64" | head -n1)" > terraform-docs && chmod +x terraform-docs && sudo mv terraform-docs /usr/bin/
curl -L "$(curl -s https://api.github.com/repos/terraform-linters/tflint/releases/latest | grep -o -E "https://.+?_linux_amd64.zip")" > tflint.zip && unzip tflint.zip && rm tflint.zip && sudo mv tflint /usr/bin/
- name: Execute pre-commit
# Run all pre-commit checks on max version supported
if: ${{ matrix.version == needs.getBaseVersion.outputs.maxVersion }}
run: pre-commit run --color=always --show-diff-on-failure --all-files

32
.gitignore vendored Normal file
View file

@ -0,0 +1,32 @@
.DS_Store
# Local .terraform directories
**/.terraform/*
# Terraform lockfile
.terraform.lock.hcl
# .tfstate files
*.tfstate
*.tfstate.*
*.tfplan
# Crash log files
crash.log
# Exclude all .tfvars files, which are likely to contain sentitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
*.tfvars
# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json
# Ignore CLI configuration files
.terraformrc
terraform.rc

27
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,27 @@
---
repos:
- repo: git://github.com/antonbabenko/pre-commit-terraform
rev: v1.48.0
hooks:
- id: terraform_fmt
- id: terraform_validate
- id: terraform_docs
- id: terraform_tflint
args:
- '--args=--only=terraform_deprecated_interpolation'
- '--args=--only=terraform_deprecated_index'
- '--args=--only=terraform_unused_declarations'
- '--args=--only=terraform_comment_syntax'
- '--args=--only=terraform_documented_outputs'
- '--args=--only=terraform_documented_variables'
- '--args=--only=terraform_typed_variables'
- '--args=--only=terraform_module_pinned_source'
- '--args=--only=terraform_naming_convention'
- '--args=--only=terraform_required_version'
- '--args=--only=terraform_required_providers'
- '--args=--only=terraform_standard_module_structure'
- '--args=--only=terraform_workspace_remote'
- repo: git://github.com/pre-commit/pre-commit-hooks
rev: v3.4.0
hooks:
- id: check-merge-conflict

0
CHANGELOG.md Normal file
View file

13
LICENSE Normal file
View file

@ -0,0 +1,13 @@
Copyright 2021 Sven Lito
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

7
Makefile Normal file
View file

@ -0,0 +1,7 @@
.PHONY: changelog release
changelog:
git-chglog -o CHANGELOG.md --next-tag `semtag final -s minor -o`
release:
semtag final -s minor

309
README.md
View file

@ -1 +1,308 @@
# terraform-aws-eventbridge # AWS EventBridge Terraform module
Terraform module to create EventBridge resources.
The following resources are currently supported:
* [Cloudwatch Event Archive](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_archive)
* [Cloudwatch Event Bus](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_bus)
* [Cloudwatch Event Permission](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_permission)
* [Cloudwatch Event Rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule)
* [Cloudwatch Event Target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target)
## Features
- [x] Creates AWS EventBridge Resources
- [x] Support AWS EventBridge Archives and Replays
- [x] Conditional creation for many types of resources
- [x] Support IAM policy attachments and various ways to create and attach additional policies
- [ ] Support monitoring usage with Cloudwatch Metrics
## Usage
### EventBridge Bus
```hcl
module "eventbridge" {
source = ""
bus_name = "my-bus"
tags = {
Name = "my-bus"
}
}
```
### EventBridge Rule
```hcl
module "eventbridge" {
source = ""
bus_name = "my-bus"
create_targets = false
rules = {
logs = {
description = "Capture log data"
event_pattern = jsonencode({ "source" : ["my.app.logs"] })
}
}
tags = {
Name = "my-bus"
}
}
```
### EventBridge Target
```hcl
module "eventbridge" {
source = ""
bus_name = "my-bus"
rules = {
logs = {
description = "Capture log data"
event_pattern = jsonencode({ "source" : ["my.app.logs"] })
}
}
targets = {
logs = [
{
name = "send-logs-to-sqs"
arn = aws_sqs_queue.queue.arn
},
{
name = "send-logs-to-cloudwatch"
arn = aws_cloudwatch_log_stream.logs.arn
}
]
}
tags = {
Name = "my-bus"
}
}
```
### EventBridge Archive
```hcl
module "eventbridge_with_archive" {
source = ""
bus_name = "my-bus"
create_archives = true
archive_config = [
{
name = "my-bus-launch-archive",
description = "EC2 AutoScaling Event archive",
retention_days = 1
event_pattern = <<PATTERN
{
"source": ["aws.autoscaling"],
"detail-type": ["EC2 Instance Launch Successful"]
}
PATTERN
}
]
tags = {
Name = "my-bus"
}
}
```
### EventBridge Permission
```hcl
module "eventbridge_with_permissions" {
source = ""
bus_name = "my-bus"
create_permissions = true
permission_config = [
{
account_id = "YOUR_ACCOUNT_ID",
statement_id = "development_account"
}
]
tags = {
Name = "my-bus"
}
}
```
## Additional IAM policies for Step Function
In addition to all supported AWS service integrations you may want to create and attach additional policies.
There are 5 supported ways to attach additional IAM policies to IAM role used by Step Function:
1. `policy_json` - JSON string or heredoc, when `attach_policy_json = true`.
2. `policy_jsons` - List of JSON strings or heredoc, when `attach_policy_jsons = true` and `number_of_policy_jsons > 0`.
3. `policy` - ARN of existing IAM policy, when `attach_policy = true`.
4. `policies` - List of ARNs of existing IAM policies, when `attach_policies = true` and `number_of_policies > 0`.
5. `policy_statements` - Map of maps to define IAM statements which will be generated as IAM policy. Requires `attach_policy_statements = true`. See `examples/complete` for more information.
## Conditional creation
Sometimes you need to have a way to create resources conditionally but Terraform does not allow usage of `count` inside `module` block, so the solution is to specify `create` arguments.
```hcl
module "eventbridge" {
source = ""
create = false # to disable all resources
create_bus = false # to control creation of the EventBridge Bus and related resources
create_rule = false # to control creation of EventBridge Rules and related resources
create_targets = false # to control creation of EventBridge Targets and related resources
create_archives = false # to control creation of EventBridge Archives
create_permissions = false # to control creation of EventBridge Permissions
create_role = false # to control creation of the IAM role and policies required for EventBridge
attach_kinesis_policy = false
attach_kinesis_firehose_policy = false
attach_sqs_policy = false
attach_ecs_policy = false
attach_lambda_policy = false
attach_sfn_policy = false
attach_cloudwatch_policy = false
attach_tracing_policy = false
# ... omitted
}
```
## Examples
* [Complete](/examples/complete)
* [Simple](/examples/simple)
* [Archive](/examples/with-archive)
* [Permissions](/examples/with-permissions)
* [SQS Target](/examples/sqs-target)
* [API-Gateway](/examples/api-gateway-event-source)
* [Input Transformation](/examples/transform-input)
* [Step Function Target](/examples/step-function-target)
## Change log
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements
| Name | Version |
|------|---------|
| terraform | >= 0.12.26 |
| aws | >= 3.19 |
## Providers
| Name | Version |
|------|---------|
| aws | >= 3.19 |
## Modules
No Modules.
## Resources
| Name |
|------|
| [aws_cloudwatch_event_archive](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_archive) |
| [aws_cloudwatch_event_bus](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_bus) |
| [aws_cloudwatch_event_permission](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_permission) |
| [aws_cloudwatch_event_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_rule) |
| [aws_cloudwatch_event_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target) |
| [aws_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy) |
| [aws_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) |
| [aws_iam_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy_attachment) |
| [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) |
| [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) |
| [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| archive\_config | A list of objects with the EventBridge Archive definitions. | `list(any)` | `[]` | no |
| attach\_cloudwatch\_policy | Controls whether the Cloudwatch policy should be added to IAM role for EventBridge Target | `bool` | `false` | no |
| attach\_ecs\_policy | Controls whether the ECS policy should be added to IAM role for EventBridge Target | `bool` | `false` | no |
| attach\_kinesis\_firehose\_policy | Controls whether the Kinesis Firehose policy should be added to IAM role for EventBridge Target | `bool` | `false` | no |
| attach\_kinesis\_policy | Controls whether the Kinesis policy should be added to IAM role for EventBridge Target | `bool` | `false` | no |
| attach\_lambda\_policy | Controls whether the Lambda Function policy should be added to IAM role for EventBridge Target | `bool` | `false` | no |
| attach\_policies | Controls whether list of policies should be added to IAM role | `bool` | `false` | no |
| attach\_policy | Controls whether policy should be added to IAM role | `bool` | `false` | no |
| attach\_policy\_json | Controls whether policy\_json should be added to IAM role | `bool` | `false` | no |
| attach\_policy\_jsons | Controls whether policy\_jsons should be added to IAM role | `bool` | `false` | no |
| attach\_policy\_statements | Controls whether policy\_statements should be added to IAM role | `bool` | `false` | no |
| attach\_sfn\_policy | Controls whether the StepFunction policy should be added to IAM role for EventBridge Target | `bool` | `false` | no |
| attach\_sqs\_policy | Controls whether the SQS policy should be added to IAM role for EventBridge Target | `bool` | `false` | no |
| attach\_tracing\_policy | Controls whether X-Ray tracing policy should be added to IAM role for EventBridge | `bool` | `false` | no |
| bus\_name | A unique name for your EventBridge Bus | `string` | `""` | no |
| cloudwatch\_target\_arns | The Amazon Resource Name (ARN) of the Cloudwatch Log Streams you want to use as EventBridge targets | `list(string)` | `[]` | no |
| create | Controls whether resources should be created | `bool` | `true` | no |
| create\_archives | Controls whether EventBridge Archive resources should be created | `bool` | `false` | no |
| create\_bus | Controls whether EventBridge Bus resource should be created | `bool` | `true` | no |
| create\_permissions | Controls whether EventBridge Permission resources should be created | `bool` | `true` | no |
| create\_role | Controls whether IAM role for Lambda Function should be created | `bool` | `true` | no |
| create\_rules | Controls whether EventBridge Rule resources should be created | `bool` | `true` | no |
| create\_targets | Controls whether EventBridge Target resources should be created | `bool` | `true` | no |
| ecs\_target\_arns | The Amazon Resource Name (ARN) of the AWS ECS Tasks you want to use as EventBridge targets | `list(string)` | `[]` | no |
| kinesis\_firehose\_target\_arns | The Amazon Resource Name (ARN) of the Kinesis Firehose Delivery Streams you want to use as EventBridge targets | `list(string)` | `[]` | no |
| kinesis\_target\_arns | The Amazon Resource Name (ARN) of the Kinesis Streams you want to use as EventBridge targets | `list(string)` | `[]` | no |
| lambda\_target\_arns | The Amazon Resource Name (ARN) of the Lambda Functions you want to use as EventBridge targets | `list(string)` | `[]` | no |
| number\_of\_policies | Number of policies to attach to IAM role | `number` | `0` | no |
| number\_of\_policy\_jsons | Number of policies JSON to attach to IAM role | `number` | `0` | no |
| permission\_config | A list of objects with EventBridge Permission definitions. | `list(any)` | `[]` | no |
| policies | List of policy statements ARN to attach to IAM role | `list(string)` | `[]` | no |
| policy | An additional policy document ARN to attach to IAM role | `string` | `null` | no |
| policy\_json | An additional policy document as JSON to attach to IAM role | `string` | `null` | no |
| policy\_jsons | List of additional policy documents as JSON to attach to IAM role | `list(string)` | `[]` | no |
| policy\_statements | Map of dynamic policy statements to attach to IAM role | `any` | `{}` | no |
| role\_description | Description of IAM role to use for Lambda Function | `string` | `null` | no |
| role\_force\_detach\_policies | Specifies to force detaching any policies the IAM role has before destroying it. | `bool` | `true` | no |
| role\_name | Name of IAM role to use for Lambda Function | `string` | `null` | no |
| role\_path | Path of IAM role to use for Lambda Function | `string` | `null` | no |
| role\_permissions\_boundary | The ARN of the policy that is used to set the permissions boundary for the IAM role used by Lambda Function | `string` | `null` | no |
| role\_tags | A map of tags to assign to IAM role | `map(string)` | `{}` | no |
| rules | A map of objects with EventBridge Rule definitions. | `map(any)` | `{}` | no |
| sfn\_target\_arns | The Amazon Resource Name (ARN) of the StepFunctions you want to use as EventBridge targets | `list(string)` | `[]` | no |
| sqs\_target\_arns | The Amazon Resource Name (ARN) of the AWS SQS Queues you want to use as EventBridge targets | `list(string)` | `[]` | no |
| tags | A map of tags to assign to resources. | `map(string)` | `{}` | no |
| targets | A Map of objects with EventBridge Target definitions. | `any` | `{}` | no |
| trusted\_entities | Step Function additional trusted entities for assuming roles (trust relationship) | `list(string)` | `[]` | no |
## Outputs
| Name | Description |
|------|-------------|
| eventbridge\_role\_arn | The ARN of the IAM role created for EventBridge |
| eventbridge\_role\_name | The name of the IAM role created for EventBridge |
| this\_eventbridge\_archive\_arns | The EventBridge Archive Arns created |
| this\_eventbridge\_bus\_arn | The EventBridge Bus Arn |
| this\_eventbridge\_bus\_name | The EventBridge Bus Name |
| this\_eventbridge\_permission\_ids | The EventBridge Permission Arns created |
| this\_eventbridge\_rule\_arns | The EventBridge Rule ARNs created |
| this\_eventbridge\_rule\_ids | The EventBridge Rule IDs created |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Authors
Module managed by [Sven Lito](https://github.com/svenlito). Check out [serverless.tf](https://serverless.tf) to learn more about doing serverless with Terraform.
## License
Apache 2 Licensed. See LICENSE for full details.

View file

@ -0,0 +1,16 @@
# EventBridge API Gateway Event Source
Configuration in this directory creates EventBridge resource configuration including an API Gateway and a SQS queue.
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.

View file

@ -0,0 +1,158 @@
terraform {
required_version = ">= 0.14.0"
required_providers {
aws = ">= 3.19"
random = ">= 0"
}
}
provider "aws" {
region = "ap-southeast-1"
# Make it faster by skipping something
skip_get_ec2_platforms = true
skip_metadata_api_check = true
skip_region_validation = true
skip_credentials_validation = true
skip_requesting_account_id = true
}
module "eventbridge" {
source = "../../"
bus_name = "${random_pet.this.id}-bus"
attach_sqs_policy = true
sqs_target_arns = [
aws_sqs_queue.queue.arn,
aws_sqs_queue.dlq.arn
]
rules = {
orders_create = {
description = "Capture all created orders",
event_pattern = jsonencode({
"detail-type" : ["Order Create"],
"source" : ["api.gateway.orders.create"]
})
}
}
targets = {
orders_create = [
{
name = "send-orders-to-sqs"
arn = aws_sqs_queue.queue.arn
dead_letter_arn = aws_sqs_queue.dlq.arn
target_id = "send-orders-to-sqs"
}
]
}
tags = {
Name = "${random_pet.this.id}-bus"
}
}
##################
# Extra resources
##################
resource "random_pet" "this" {
length = 2
}
module "api_gateway" {
source = "terraform-aws-modules/apigateway-v2/aws"
version = "0.14.0"
name = "${random_pet.this.id}-http"
description = "My ${random_pet.this.id} HTTP API Gateway"
protocol_type = "HTTP"
create_api_domain_name = false
integrations = {
"POST /orders/create" = {
integration_type = "AWS_PROXY"
integration_subtype = "EventBridge-PutEvents"
credentials_arn = module.apigateway_put_events_to_eventbridge_role.this_iam_role_arn
request_parameters = jsonencode({
EventBusName = module.eventbridge.this_eventbridge_bus_name,
Source = "api.gateway.orders.create",
DetailType = "Order Create",
Detail = "$request.body",
Time = "$context.requestTimeEpoch"
})
payload_format_version = "1.0"
}
}
}
module "apigateway_put_events_to_eventbridge_role" {
source = "terraform-aws-modules/iam/aws//modules/iam-assumable-role"
version = "3.13.0"
create_role = true
role_name = "apigateway-put-events-to-eventbridge"
role_requires_mfa = false
trusted_role_services = [
"apigateway.amazonaws.com"
]
custom_role_policy_arns = [
module.apigateway_put_events_to_eventbridge_policy.arn
]
}
module "apigateway_put_events_to_eventbridge_policy" {
source = "terraform-aws-modules/iam/aws//modules/iam-policy"
version = "3.13.0"
name = "apigateway-put-events-to-eventbridge"
path = "/"
description = "Allow PutEvents to EventBridge"
policy = data.aws_iam_policy_document.apigateway_put_events_to_eventbridge_policy.json
}
data "aws_iam_policy_document" "apigateway_put_events_to_eventbridge_policy" {
statement {
sid = "AllowPutEvents"
actions = ["events:PutEvents"]
resources = [module.eventbridge.this_eventbridge_bus_arn]
}
depends_on = [module.eventbridge]
}
resource "aws_sqs_queue" "dlq" {
name = "${random_pet.this.id}-dlq"
}
resource "aws_sqs_queue" "queue" {
name = random_pet.this.id
}
resource "aws_sqs_queue_policy" "queue" {
queue_url = aws_sqs_queue.queue.id
policy = data.aws_iam_policy_document.queue.json
}
data "aws_iam_policy_document" "queue" {
statement {
sid = "AllowSendMessage"
actions = ["sqs:SendMessage"]
principals {
type = "Service"
identifiers = ["events.amazonaws.com"]
}
resources = [aws_sqs_queue.queue.arn]
}
}

View file

@ -0,0 +1,28 @@
output "this_eventbridge_bus_name" {
description = "The EventBridge Bus Name"
value = module.eventbridge.this_eventbridge_bus_name
}
output "this_eventbridge_bus_arn" {
description = "The EventBridge Bus Arn"
value = module.eventbridge.this_eventbridge_bus_arn
}
output "this_eventbridge_rule_ids" {
description = "The EventBridge Rule IDs created"
value = module.eventbridge.this_eventbridge_rule_ids
}
output "this_eventbridge_rule_arns" {
description = "The EventBridge Rule ARNs created"
value = module.eventbridge.this_eventbridge_rule_arns
}
output "eventbridge_role_arn" {
description = "The ARN of the IAM role created for EventBridge"
value = module.eventbridge.eventbridge_role_arn
}
output "eventbridge_role_name" {
description = "The name of the IAM role created for EventBridge"
value = module.eventbridge.eventbridge_role_name
}

View file

@ -0,0 +1,39 @@
{
"data": {
"destination": {
"name": "accountName"
},
"orderData": {
"sourceOrderId": "1234512345",
"items": [
{
"sku": "Business Cards",
"sourceItemId": "1234512346",
"components": [
{
"code": "Content",
"fetch": true,
"path": "http://www.w2psite.com/businessCard.pdf"
}
]
}
],
"shipments": [
{
"shipTo": {
"name": "John Doe",
"companyName": "Acme",
"address1": "1234 Main St.",
"town": "Capitol",
"postcode": "12345",
"isoCountry": "US"
},
"carrier":{
"code": "fedex",
"service": "ground"
}
}
]
}
}
}

View file

View file

@ -0,0 +1,68 @@
terraform {
required_version = ">= 0.14.0"
required_providers {
aws = ">= 3.19"
random = ">= 0"
}
}
provider "aws" {
region = "ap-southeast-1"
# Make it faster by skipping something
skip_get_ec2_platforms = true
skip_metadata_api_check = true
skip_region_validation = true
skip_credentials_validation = true
skip_requesting_account_id = true
}
module "eventbridge" {
source = "../../"
bus_name = "${random_pet.this.id}-bus"
attach_cloudwatch_policy = true
cloudwatch_target_arns = [
aws_cloudwatch_log_group.this.arn
]
rules = {
orders = {
description = "Capture all created orders",
event_pattern = jsonencode({ "source" : ["orders.create"] })
}
}
targets = {
orders = [
{
name = "log-orders-to-cloudwatch"
arn = aws_cloudwatch_log_group.this.arn
}
]
}
tags = {
Name = "${random_pet.this.id}-bus"
}
}
##################
# Extra resources
##################
resource "random_pet" "this" {
length = 2
}
resource "aws_cloudwatch_log_group" "this" {
name = "/aws/events/${random_pet.this.id}"
tags = {
Name = "${random_pet.this.id}-log-group"
}
}

View file

@ -0,0 +1,5 @@
output "eventbridge_bus_arn" {
description = "The EventBridge Bus ARN"
value = module.eventbridge.this_eventbridge_bus_arn
}

View file

View file

@ -0,0 +1,15 @@
# EventBridge Complete Example
Configuration in this directory creates EventBridge resource configuration including an SQS queue, Kinesis stream, and DynamoDB table.
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.

221
examples/complete/main.tf Normal file
View file

@ -0,0 +1,221 @@
terraform {
required_version = ">= 0.14.0"
required_providers {
aws = ">= 3.19"
random = ">= 0"
}
}
provider "aws" {
region = "ap-southeast-1"
# Make it faster by skipping something
skip_get_ec2_platforms = true
skip_metadata_api_check = true
skip_region_validation = true
skip_credentials_validation = true
skip_requesting_account_id = true
}
resource "random_pet" "this" {
length = 2
}
module "eventbridge" {
source = "../../"
bus_name = "${random_pet.this.id}-bus"
create_bus = true
create_rules = true
create_targets = true
create_archives = true
create_permissions = true
attach_tracing_policy = true
attach_kinesis_policy = true
attach_kinesis_firehose_policy = true
attach_sqs_policy = true
attach_ecs_policy = true
attach_lambda_policy = true
attach_sfn_policy = true
attach_cloudwatch_policy = true
sqs_target_arns = [aws_sqs_queue.queue.arn]
ecs_target_arns = []
kinesis_target_arns = [aws_kinesis_stream.this.arn]
kinesis_firehose_target_arns = []
lambda_target_arns = []
sfn_target_arns = []
cloudwatch_target_arns = [aws_cloudwatch_log_group.this.arn]
permission_config = [
{
account_id = "099720109477",
statement_id = "canonical"
},
{
account_id = "099720109466",
statement_id = "canonical_two"
}
]
archive_config = [
{
description = "some archive"
retention_days = 1
event_pattern = <<PATTERN
{
"source": ["myapp.orders"]
}
PATTERN
}
]
rules = {
orders = {
description = "Capture all order data"
event_pattern = jsonencode({ "source" : ["myapp.orders"] })
enabled = false
}
}
targets = {
orders = [
{
name = "send-orders-to-sqs"
arn = aws_sqs_queue.queue.arn
dead_letter_arn = aws_sqs_queue.dlq.arn
},
{
name = "send-orders-to-kinesis"
arn = aws_kinesis_stream.this.arn
dead_letter_arn = aws_sqs_queue.dlq.arn
input_transformer = local.kinesis_input_transformer
},
{
name = "log-orders-to-cloudwatch"
arn = aws_cloudwatch_log_group.this.arn
}
]
}
######################
# Additional policies
######################
attach_policy_json = true
policy_json = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"xray:GetSamplingStatisticSummaries"
],
"Resource": ["*"]
}
]
}
EOF
attach_policy_jsons = true
policy_jsons = [<<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"xray:*"
],
"Resource": ["*"]
}
]
}
EOF
]
number_of_policy_jsons = 1
attach_policy = true
policy = "arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess"
attach_policies = true
policies = ["arn:aws:iam::aws:policy/AWSXrayReadOnlyAccess"]
number_of_policies = 1
attach_policy_statements = true
policy_statements = {
dynamodb = {
effect = "Allow",
actions = ["dynamodb:BatchWriteItem"],
resources = ["arn:aws:dynamodb:eu-west-1:052212379155:table/Test"]
},
s3_read = {
effect = "Deny",
actions = ["s3:HeadObject", "s3:GetObject"],
resources = ["arn:aws:s3:::my-bucket/*"]
}
}
###########################
# END: Additional policies
###########################
}
locals {
kinesis_input_transformer = {
input_paths = {
order_id = "$.detail.order_id"
}
input_template = <<EOF
{
"id": <order_id>
}
EOF
}
}
##################
# Extra resources
##################
resource "aws_kinesis_stream" "this" {
name = random_pet.this.id
shard_count = 1
}
resource "aws_sqs_queue" "queue" {
name = "${random_pet.this.id}-queue"
}
resource "aws_sqs_queue" "dlq" {
name = "${random_pet.this.id}-dlq"
}
resource "aws_sqs_queue_policy" "queue" {
queue_url = aws_sqs_queue.queue.id
policy = data.aws_iam_policy_document.queue.json
}
data "aws_iam_policy_document" "queue" {
statement {
sid = "events-policy"
actions = ["sqs:SendMessage"]
principals {
type = "Service"
identifiers = ["events.amazonaws.com"]
}
resources = [aws_sqs_queue.queue.arn]
}
}
resource "aws_cloudwatch_log_group" "this" {
name = "/aws/events/${random_pet.this.id}"
tags = {
Name = "${random_pet.this.id}-log-group"
}
}

View file

@ -0,0 +1,14 @@
output "eventbridge_bus_arn" {
description = "The EventBridge Bus ARN"
value = module.eventbridge.this_eventbridge_bus_arn
}
output "eventbridge_rule_ids" {
description = "The EventBridge Rule IDs"
value = module.eventbridge.this_eventbridge_rule_ids
}
output "eventbridge_rule_arns" {
description = "The EventBridge Rule ARNs"
value = module.eventbridge.this_eventbridge_rule_arns
}

View file

16
examples/simple/README.md Normal file
View file

@ -0,0 +1,16 @@
# EventBridge Simple Example
Configuration in this directory creates EventBridge resource configuration.
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.

34
examples/simple/main.tf Normal file
View file

@ -0,0 +1,34 @@
terraform {
required_version = ">= 0.14.0"
required_providers {
aws = ">= 3.19"
random = ">= 0"
}
}
provider "aws" {
region = "ap-southeast-1"
# Make it faster by skipping something
skip_get_ec2_platforms = true
skip_metadata_api_check = true
skip_region_validation = true
skip_credentials_validation = true
skip_requesting_account_id = true
}
resource "random_pet" "this" {
length = 2
}
module "eventbridge" {
source = "../../"
bus_name = "${random_pet.this.id}-bus"
tags = {
Name = "${random_pet.this.id}-bus"
}
}

View file

@ -0,0 +1,5 @@
output "eventbridge_bus_arn" {
description = "The EventBridge Bus ARN"
value = module.eventbridge.this_eventbridge_bus_arn
}

View file

View file

@ -0,0 +1,17 @@
# EventBridge SQS Example
Configuration in this directory creates EventBridge resource configuration.
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.

115
examples/sqs-target/main.tf Normal file
View file

@ -0,0 +1,115 @@
terraform {
required_version = ">= 0.14.0"
required_providers {
aws = ">= 3.19"
random = ">= 0"
}
}
provider "aws" {
region = "ap-southeast-1"
# Make it faster by skipping something
skip_get_ec2_platforms = true
skip_metadata_api_check = true
skip_region_validation = true
skip_credentials_validation = true
skip_requesting_account_id = true
}
module "eventbridge" {
source = "../../"
bus_name = "${random_pet.this.id}-bus"
attach_sqs_policy = true
sqs_target_arns = [
aws_sqs_queue.queue.arn,
aws_sqs_queue.fifo.arn,
aws_sqs_queue.dlq.arn
]
rules = {
orders = {
description = "Capture all created orders",
event_pattern = jsonencode({ "source" : ["orders.create"] })
}
}
targets = {
orders = [
{
name = "send-orders-to-sqs"
arn = aws_sqs_queue.queue.arn
},
{
name = "send-orders-to-sqs-wth-dead-letter"
arn = aws_sqs_queue.queue.arn
dead_letter_arn = aws_sqs_queue.dlq.arn
},
{
name = "send-orders-to-sqs-with-retry-policy"
arn = aws_sqs_queue.queue.arn
dead_letter_arn = aws_sqs_queue.dlq.arn
retry_policy = {
maximum_retry_attempts = 10
maximum_event_age_in_seconds = 300
}
},
{
name = "send-orders-to-fifo-sqs"
arn = aws_sqs_queue.fifo.arn
dead_letter_arn = aws_sqs_queue.dlq.arn
message_group_id = "send-orders-to-fifo-sqs"
}
]
}
tags = {
Name = "${random_pet.this.id}-bus"
}
}
##################
# Extra resources
##################
resource "random_pet" "this" {
length = 2
}
resource "aws_sqs_queue" "queue" {
name = random_pet.this.id
}
resource "aws_sqs_queue" "fifo" {
name = "${random_pet.this.id}.fifo"
fifo_queue = true
content_based_deduplication = true
}
resource "aws_sqs_queue" "dlq" {
name = "${random_pet.this.id}-dlq"
}
resource "aws_sqs_queue_policy" "queue" {
queue_url = aws_sqs_queue.queue.id
policy = data.aws_iam_policy_document.queue.json
}
data "aws_iam_policy_document" "queue" {
statement {
sid = "events-policy"
actions = ["sqs:SendMessage"]
principals {
type = "Service"
identifiers = ["events.amazonaws.com"]
}
resources = [
aws_sqs_queue.queue.arn,
aws_sqs_queue.fifo.arn
]
}
}

View file

@ -0,0 +1,14 @@
output "eventbridge_bus_arn" {
description = "The EventBridge Bus ARN"
value = module.eventbridge.this_eventbridge_bus_arn
}
output "eventbridge_rule_ids" {
description = "The EventBridge Rule IDs"
value = module.eventbridge.this_eventbridge_rule_ids
}
output "eventbridge_rule_arns" {
description = "The EventBridge Rule ARNs"
value = module.eventbridge.this_eventbridge_rule_arns
}

View file

View file

View file

@ -0,0 +1,79 @@
terraform {
required_version = ">= 0.14.0"
required_providers {
aws = ">= 3.19"
random = ">= 0"
}
}
provider "aws" {
region = "ap-southeast-1"
# Make it faster by skipping something
skip_get_ec2_platforms = true
skip_metadata_api_check = true
skip_region_validation = true
skip_credentials_validation = true
skip_requesting_account_id = true
}
module "eventbridge" {
source = "../../"
bus_name = "${random_pet.this.id}-bus"
attach_sfn_policy = true
sfn_target_arns = [module.step_function.this_state_machine_arn]
rules = {
orders = {
description = "Capture order data"
event_pattern = jsonencode({ "source" : ["orders.create"] })
}
}
targets = {
orders = [
{
name = "process-order-with-sfn"
arn = module.step_function.this_state_machine_arn
attach_role_arn = true
}
]
}
tags = {
Name = "${random_pet.this.id}-bus"
}
}
##################
# Extra resources
##################
resource "random_pet" "this" {
length = 2
}
module "step_function" {
source = "terraform-aws-modules/step-functions/aws"
version = "1.2.0"
name = random_pet.this.id
definition = jsonencode(yamldecode(templatefile("sfn.asl.yaml", {})))
trusted_entities = ["events.amazonaws.com"]
service_integrations = {
stepfunction = {
stepfunction = ["*"]
}
}
tags = {
Name = "${random_pet.this.id}-step-function"
}
}

View file

@ -0,0 +1,5 @@
output "eventbridge_bus_arn" {
description = "The EventBridge Bus ARN"
value = module.eventbridge.this_eventbridge_bus_arn
}

View file

@ -0,0 +1,12 @@
---
Comment: Default Step Function
StartAt: Hello
States:
Hello:
Type: Pass
Result: Hello
Next: World
World:
Type: Pass
Result: World
End: true

View file

@ -0,0 +1,17 @@
# EventBridge Input Transform Example
Configuration in this directory creates EventBridge resource configuration.
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.

View file

@ -0,0 +1,84 @@
terraform {
required_version = ">= 0.14.0"
required_providers {
aws = ">= 3.19"
random = ">= 0"
}
}
provider "aws" {
region = "ap-southeast-1"
# Make it faster by skipping something
skip_get_ec2_platforms = true
skip_metadata_api_check = true
skip_region_validation = true
skip_credentials_validation = true
skip_requesting_account_id = true
}
module "eventbridge" {
source = "../../"
bus_name = "${random_pet.this.id}-bus"
rules = {
orders = {
description = "Capture all order data"
event_pattern = jsonencode({ "source" : ["orders.create"] })
}
}
targets = {
orders = [
{
name = "send-orders-to-sqs"
arn = aws_sqs_queue.queue.arn
input_transformer = {
input_paths = {
order_id = "$.detail.order_id"
}
input_template = <<EOF
{
"id": <order_id>
}
EOF
}
}
]
}
tags = {
Name = "${random_pet.this.id}-bus"
}
}
##################
# Extra resources
##################
resource "random_pet" "this" {
length = 2
}
resource "aws_sqs_queue" "queue" {
name = "${random_pet.this.id}-queue"
}
resource "aws_sqs_queue_policy" "queue" {
queue_url = aws_sqs_queue.queue.id
policy = data.aws_iam_policy_document.queue.json
}
data "aws_iam_policy_document" "queue" {
statement {
sid = "events-policy"
actions = ["sqs:SendMessage"]
principals {
type = "Service"
identifiers = ["events.amazonaws.com"]
}
resources = [aws_sqs_queue.queue.arn]
}
}

View file

@ -0,0 +1,5 @@
output "eventbridge_bus_arn" {
description = "The EventBridge Bus ARN"
value = module.eventbridge.this_eventbridge_bus_arn
}

View file

View file

@ -0,0 +1,16 @@
# EventBridge Simple Example
Configuration in this directory creates EventBridge resource configuration.
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.

View file

@ -0,0 +1,100 @@
terraform {
required_version = ">= 0.14.0"
required_providers {
aws = ">= 3.19"
random = ">= 0"
}
}
provider "aws" {
region = "ap-southeast-1"
# Make it faster by skipping something
skip_get_ec2_platforms = true
skip_metadata_api_check = true
skip_region_validation = true
skip_credentials_validation = true
skip_requesting_account_id = true
}
resource "random_pet" "this" {
length = 2
}
module "eventbridge" {
source = "../../"
create_archives = true
archive_config = [
{
name = "${random_pet.this.id}-launch-archive",
description = "${random_pet.this.id}-launch-archive",
retention_days = 1
event_pattern = <<PATTERN
{
"source": ["aws.autoscaling"],
"detail-type": ["EC2 Instance Launch Successful"]
}
PATTERN
},
{
name = "${random_pet.this.id}-termination-archive",
description = "${random_pet.this.id}-termination-archive",
retention_days = 1
event_pattern = <<PATTERN
{
"source": ["aws.ec2"],
"detail-type": ["EC2 Instance State-change Notification"],
"detail": {
"state": ["terminated"]
}
}
PATTERN
}
]
bus_name = "${random_pet.this.id}-bus"
tags = {
Name = "${random_pet.this.id}-bus"
}
}
module "eventbridge_archive_only" {
source = "../../"
create_bus = false
create_rules = false
create_targets = false
create_archives = true
archive_config = [
{
event_source_arn = aws_cloudwatch_event_bus.pre_existing_bus.arn
name = "${random_pet.this.id}-launch-archive",
description = "${random_pet.this.id}-launch-archive",
retention_days = 1
event_pattern = <<PATTERN
{
"source": ["aws.autoscaling"],
"detail-type": ["EC2 Instance Launch Successful"]
}
PATTERN
}
]
tags = {
Name = "${random_pet.this.id}-bus"
}
}
##################
# Extra resources
##################
resource "aws_cloudwatch_event_bus" "pre_existing_bus" {
name = "${random_pet.this.id}-bus"
}

View file

@ -0,0 +1,10 @@
output "eventbridge_bus_arn" {
description = "The EventBridge Bus ARN"
value = module.eventbridge.this_eventbridge_bus_arn
}
output "eventbridge_archive_arns" {
description = "The EventBridge Archive ARNs"
value = module.eventbridge.this_eventbridge_archive_arns
}

View file

View file

@ -0,0 +1,16 @@
# EventBridge Simple Example
Configuration in this directory creates EventBridge resource configuration.
## Usage
To run this example you need to execute:
```bash
$ terraform init
$ terraform plan
$ terraform apply
```
Note that this example may create resources which cost money. Run `terraform destroy` when you don't need these resources.

View file

@ -0,0 +1,50 @@
terraform {
required_version = ">= 0.14.0"
required_providers {
aws = ">= 3.19"
random = ">= 0"
}
}
provider "aws" {
region = "ap-southeast-1"
# Make it faster by skipping something
skip_get_ec2_platforms = true
skip_metadata_api_check = true
skip_region_validation = true
skip_credentials_validation = true
skip_requesting_account_id = true
}
module "eventbridge" {
source = "../../"
create_permissions = true
permission_config = [
{
account_id = "099720109477",
statement_id = "canonical"
},
{
account_id = "099720109466",
statement_id = "canonical_two"
}
]
bus_name = "${random_pet.this.id}-bus"
tags = {
Name = "${random_pet.this.id}-bus"
}
}
##################
# Extra resources
##################
resource "random_pet" "this" {
length = 2
}

View file

@ -0,0 +1,9 @@
output "eventbridge_bus_arn" {
description = "The EventBridge Bus ARN"
value = module.eventbridge.this_eventbridge_bus_arn
}
output "this_eventbridge_permission_ids" {
description = "The EventBridge Permissions"
value = module.eventbridge.this_eventbridge_permission_ids
}

View file

408
iam.tf Normal file
View file

@ -0,0 +1,408 @@
locals {
create_role = var.create && var.create_bus && var.create_role
role_name = local.create_role ? coalesce(var.role_name, var.bus_name, "*") : null
}
###########
# IAM role
###########
data "aws_iam_policy_document" "assume_role" {
count = local.create_role ? 1 : 0
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = distinct(concat(["events.amazonaws.com"], var.trusted_entities))
}
}
}
resource "aws_iam_role" "eventbridge" {
count = local.create_role ? 1 : 0
name = local.role_name
description = var.role_description
path = var.role_path
force_detach_policies = var.role_force_detach_policies
permissions_boundary = var.role_permissions_boundary
assume_role_policy = data.aws_iam_policy_document.assume_role[0].json
tags = merge(var.tags, var.role_tags)
}
#####################
# Tracing with X-Ray
#####################
# Copying AWS managed policy to be able to attach the same policy with
# multiple roles without overwrites by another resources
data "aws_iam_policy" "tracing" {
count = local.create_role && var.attach_tracing_policy ? 1 : 0
arn = "arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess"
}
resource "aws_iam_policy" "tracing" {
count = local.create_role && var.attach_tracing_policy ? 1 : 0
name = "${local.role_name}-tracing"
policy = data.aws_iam_policy.tracing[0].policy
}
resource "aws_iam_policy_attachment" "tracing" {
count = local.create_role && var.attach_tracing_policy ? 1 : 0
name = "${local.role_name}-tracing"
roles = [aws_iam_role.eventbridge[0].name]
policy_arn = aws_iam_policy.tracing[0].arn
}
##################
# Kinesis Config
##################
data "aws_iam_policy_document" "kinesis" {
count = local.create_role && var.attach_kinesis_policy ? 1 : 0
statement {
sid = "KinesisAccess"
effect = "Allow"
actions = ["kinesis:PutRecord"]
resources = var.kinesis_target_arns
}
}
resource "aws_iam_policy" "kinesis" {
count = local.create_role && var.attach_kinesis_policy ? 1 : 0
name = "${local.role_name}-kinesis"
policy = data.aws_iam_policy_document.kinesis[0].json
}
resource "aws_iam_policy_attachment" "kinesis" {
count = local.create_role && var.attach_kinesis_policy ? 1 : 0
name = "${local.role_name}-kinesis"
roles = [aws_iam_role.eventbridge[0].name]
policy_arn = aws_iam_policy.kinesis[0].arn
}
##########################
# Kinesis Firehose Config
##########################
data "aws_iam_policy_document" "kinesis_firehose" {
count = local.create_role && var.attach_kinesis_firehose_policy ? 1 : 0
statement {
sid = "KinesisFirehoseAccess"
effect = "Allow"
actions = ["firehose:PutRecord"]
resources = var.kinesis_firehose_target_arns
}
}
resource "aws_iam_policy" "kinesis_firehose" {
count = local.create_role && var.attach_kinesis_firehose_policy ? 1 : 0
name = "${local.role_name}-kinesis-firehose"
policy = data.aws_iam_policy_document.kinesis_firehose[0].json
}
resource "aws_iam_policy_attachment" "kinesis_firehose" {
count = local.create_role && var.attach_kinesis_firehose_policy ? 1 : 0
name = "${local.role_name}-kinesis-firehose"
roles = [aws_iam_role.eventbridge[0].name]
policy_arn = aws_iam_policy.kinesis_firehose[0].arn
}
#############
# SQS Config
#############
data "aws_iam_policy_document" "sqs" {
count = local.create_role && var.attach_sqs_policy ? 1 : 0
statement {
sid = "SQSAccess"
effect = "Allow"
actions = [
"sqs:sendMessage*",
"kms:Decrypt",
"kms:GenerateDataKey"
]
resources = var.sqs_target_arns
}
}
resource "aws_iam_policy" "sqs" {
count = local.create_role && var.attach_sqs_policy ? 1 : 0
name = "${local.role_name}-sqs"
policy = data.aws_iam_policy_document.sqs[0].json
}
resource "aws_iam_policy_attachment" "sqs" {
count = local.create_role && var.attach_sqs_policy ? 1 : 0
name = "${local.role_name}-sqs"
roles = [aws_iam_role.eventbridge[0].name]
policy_arn = aws_iam_policy.sqs[0].arn
}
#############
# ECS Config
#############
data "aws_iam_policy_document" "ecs" {
count = local.create_role && var.attach_ecs_policy ? 1 : 0
statement {
sid = "ECSAccess"
effect = "Allow"
actions = ["ecs:RunTask"]
resources = var.ecs_target_arns
}
statement {
sid = "PassRole"
effect = "Allow"
actions = ["iam:PassRole"]
resources = [aws_iam_role.eventbridge[0].arn]
}
}
resource "aws_iam_policy" "ecs" {
count = local.create_role && var.attach_ecs_policy ? 1 : 0
name = "${local.role_name}-ecs"
policy = data.aws_iam_policy_document.ecs[0].json
}
resource "aws_iam_policy_attachment" "ecs" {
count = local.create_role && var.attach_ecs_policy ? 1 : 0
name = "${local.role_name}-ecs"
roles = [aws_iam_role.eventbridge[0].name]
policy_arn = aws_iam_policy.ecs[0].arn
}
#########################
# Lambda Function Config
#########################
data "aws_iam_policy_document" "lambda" {
count = local.create_role && var.attach_lambda_policy ? 1 : 0
statement {
sid = "LambdaAccess"
effect = "Allow"
actions = ["lambda:InvokeFunction"]
resources = var.lambda_target_arns
}
}
resource "aws_iam_policy" "lambda" {
count = local.create_role && var.attach_lambda_policy ? 1 : 0
name = "${local.role_name}-lambda"
policy = data.aws_iam_policy_document.lambda[0].json
}
resource "aws_iam_policy_attachment" "lambda" {
count = local.create_role && var.attach_lambda_policy ? 1 : 0
name = "${local.role_name}-lambda"
roles = [aws_iam_role.eventbridge[0].name]
policy_arn = aws_iam_policy.lambda[0].arn
}
######################
# StepFunction Config
######################
data "aws_iam_policy_document" "sfn" {
count = local.create_role && var.attach_sfn_policy ? 1 : 0
statement {
sid = "StepFunctionAccess"
effect = "Allow"
actions = ["states:StartExecution"]
resources = var.sfn_target_arns
}
}
resource "aws_iam_policy" "sfn" {
count = local.create_role && var.attach_sfn_policy ? 1 : 0
name = "${local.role_name}-sfn"
policy = data.aws_iam_policy_document.sfn[0].json
}
resource "aws_iam_policy_attachment" "sfn" {
count = local.create_role && var.attach_sfn_policy ? 1 : 0
name = "${local.role_name}-sfn"
roles = [aws_iam_role.eventbridge[0].name]
policy_arn = aws_iam_policy.sfn[0].arn
}
####################
# Cloudwatch Config
####################
data "aws_iam_policy_document" "cloudwatch" {
count = local.create_role && var.attach_cloudwatch_policy ? 1 : 0
statement {
sid = "CloudwatchAccess"
effect = "Allow"
actions = [
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:PutLogEvents"
]
resources = var.cloudwatch_target_arns
}
}
resource "aws_iam_policy" "cloudwatch" {
count = local.create_role && var.attach_cloudwatch_policy ? 1 : 0
name = "${local.role_name}-cloudwatch"
policy = data.aws_iam_policy_document.cloudwatch[0].json
}
resource "aws_iam_policy_attachment" "cloudwatch" {
count = local.create_role && var.attach_cloudwatch_policy ? 1 : 0
name = "${local.role_name}-cloudwatch"
roles = [aws_iam_role.eventbridge[0].name]
policy_arn = aws_iam_policy.cloudwatch[0].arn
}
###########################
# Additional policy (JSON)
###########################
resource "aws_iam_policy" "additional_json" {
count = local.create_role && var.attach_policy_json ? 1 : 0
name = local.role_name
policy = var.policy_json
}
resource "aws_iam_policy_attachment" "additional_json" {
count = local.create_role && var.attach_policy_json ? 1 : 0
name = local.role_name
roles = [aws_iam_role.eventbridge[0].name]
policy_arn = aws_iam_policy.additional_json[0].arn
}
#####################################
# Additional policies (list of JSON)
#####################################
resource "aws_iam_policy" "additional_jsons" {
count = local.create_role && var.attach_policy_jsons ? var.number_of_policy_jsons : 0
name = "${local.role_name}-${count.index}"
policy = var.policy_jsons[count.index]
}
resource "aws_iam_policy_attachment" "additional_jsons" {
count = local.create_role && var.attach_policy_jsons ? var.number_of_policy_jsons : 0
name = "${local.role_name}-${count.index}"
roles = [aws_iam_role.eventbridge[0].name]
policy_arn = aws_iam_policy.additional_jsons[count.index].arn
}
###########################
# ARN of additional policy
###########################
resource "aws_iam_role_policy_attachment" "additional_one" {
count = local.create_role && var.attach_policy ? 1 : 0
role = aws_iam_role.eventbridge[0].name
policy_arn = var.policy
}
######################################
# List of ARNs of additional policies
######################################
resource "aws_iam_role_policy_attachment" "additional_many" {
count = local.create_role && var.attach_policies ? var.number_of_policies : 0
role = aws_iam_role.eventbridge[0].name
policy_arn = var.policies[count.index]
}
###############################
# Additional policy statements
###############################
data "aws_iam_policy_document" "additional_inline" {
count = local.create_role && var.attach_policy_statements ? 1 : 0
dynamic "statement" {
for_each = var.policy_statements
content {
sid = lookup(statement.value, "sid", replace(statement.key, "/[^0-9A-Za-z]*/", ""))
effect = lookup(statement.value, "effect", null)
actions = lookup(statement.value, "actions", null)
not_actions = lookup(statement.value, "not_actions", null)
resources = lookup(statement.value, "resources", null)
not_resources = lookup(statement.value, "not_resources", null)
dynamic "principals" {
for_each = lookup(statement.value, "principals", [])
content {
type = principals.value.type
identifiers = principals.value.identifiers
}
}
dynamic "not_principals" {
for_each = lookup(statement.value, "not_principals", [])
content {
type = not_principals.value.type
identifiers = not_principals.value.identifiers
}
}
dynamic "condition" {
for_each = lookup(statement.value, "condition", [])
content {
test = condition.value.test
variable = condition.value.variable
values = condition.value.values
}
}
}
}
}
resource "aws_iam_policy" "additional_inline" {
count = local.create_role && var.attach_policy_statements ? 1 : 0
name = "${local.role_name}-inline"
policy = data.aws_iam_policy_document.additional_inline[0].json
}
resource "aws_iam_policy_attachment" "additional_inline" {
count = local.create_role && var.attach_policy_statements ? 1 : 0
name = local.role_name
roles = [aws_iam_role.eventbridge[0].name]
policy_arn = aws_iam_policy.additional_inline[0].arn
}

166
main.tf Normal file
View file

@ -0,0 +1,166 @@
locals {
eventbridge_rules = flatten([
for index, rule in var.rules :
merge(rule, { "name" = index })
])
eventbridge_targets = flatten([
for index, rule in var.rules : [
for target in var.targets[index] :
merge(target, { "rule" = index })
] if length(var.targets) != 0
])
}
resource "aws_cloudwatch_event_bus" "this" {
count = var.create && var.create_bus ? 1 : 0
name = var.bus_name
tags = var.tags
}
resource "aws_cloudwatch_event_rule" "this" {
for_each = var.create && var.create_rules ? {
for rule in local.eventbridge_rules : rule.name => rule
} : {}
name = "${replace(each.value.name, "_", "-")}-rule"
event_bus_name = aws_cloudwatch_event_bus.this[0].name
description = lookup(each.value, "description", null)
name_prefix = lookup(each.value, "name_prefix", null)
is_enabled = lookup(each.value, "enabled", true)
event_pattern = lookup(each.value, "event_pattern", null)
schedule_expression = lookup(each.value, "schedule_expression", null)
role_arn = aws_iam_role.eventbridge[0].arn
tags = merge(var.tags, {
Name = "${replace(each.value.name, "_", "-")}-rule"
})
}
resource "aws_cloudwatch_event_target" "this" {
for_each = var.create && var.create_targets ? {
for target in local.eventbridge_targets : target.name => target
} : tomap({})
event_bus_name = aws_cloudwatch_event_bus.this[0].name
rule = "${replace(each.value.rule, "_", "-")}-rule"
arn = each.value.arn
role_arn = lookup(each.value, "attach_role_arn", null) != null ? aws_iam_role.eventbridge[0].arn : null
target_id = lookup(each.value, "target_id", null)
input = lookup(each.value, "input", null)
input_path = lookup(each.value, "input_path", null)
dynamic "run_command_targets" {
for_each = lookup(each.value, "run_command_targets", null) != null ? [true] : []
content {
key = run_command_targets.value.key
values = run_command_targets.value.values
}
}
dynamic "ecs_target" {
for_each = lookup(each.value, "ecs_target", null) != null ? [true] : []
content {
group = lookup(ecs_target.value, "group", null)
launch_type = lookup(ecs_target.value, "launch_type", null)
platform_version = lookup(ecs_target.value, "platform_version", null)
task_count = lookup(ecs_target.value, "task_count", null)
task_definition_arn = ecs_target.value.task_definition_arn
dynamic "network_configuration" {
for_each = lookup(ecs_target.value, "network_configuration", null) != null ? [true] : []
content {
subnets = network_configuration.value.subnets
security_groups = lookup(network_configuration.value, "security_groups", null)
assign_public_ip = lookup(network_configuration.value, "assign_public_ip", null)
}
}
}
}
dynamic "batch_target" {
for_each = lookup(each.value, "batch_target", null) != null ? [true] : []
content {
job_definition = batch_target.value.job_definition
job_name = batch_target.value.job_name
array_size = lookup(batch_target.value, "array_size", null)
job_attempts = lookup(batch_target.value, "job_attempts", null)
}
}
dynamic "kinesis_target" {
for_each = lookup(each.value, "kinesis_target", null) != null ? [true] : []
content {
partition_key_path = lookup(kinesis_target.value, "partition_key_path", null)
}
}
dynamic "sqs_target" {
for_each = lookup(each.value, "message_group_id", null) != null ? [true] : []
content {
message_group_id = each.value.message_group_id
}
}
dynamic "input_transformer" {
for_each = lookup(each.value, "input_transformer", null) != null ? [
each.value.input_transformer
] : []
content {
input_paths = input_transformer.value.input_paths
input_template = input_transformer.value.input_template
}
}
dynamic "dead_letter_config" {
for_each = lookup(each.value, "dead_letter_arn", null) != null ? [true] : []
content {
arn = each.value.dead_letter_arn
}
}
dynamic "retry_policy" {
for_each = lookup(each.value, "retry_policy", null) != null ? [
each.value.retry_policy
] : []
content {
maximum_event_age_in_seconds = retry_policy.value.maximum_event_age_in_seconds
maximum_retry_attempts = retry_policy.value.maximum_retry_attempts
}
}
}
resource "aws_cloudwatch_event_archive" "this" {
for_each = var.create && var.create_archives ? {
for k, v in var.archive_config : k => v
} : {}
name = each.value.name
event_source_arn = lookup(each.value, "event_source_arn", null) == null ? aws_cloudwatch_event_bus.this[0].arn : null
description = lookup(each.value, "description", null)
event_pattern = lookup(each.value, "event_pattern", null)
retention_days = lookup(each.value, "retention_days", null)
}
resource "aws_cloudwatch_event_permission" "this" {
for_each = var.create && var.create_permissions ? {
for permission in var.permission_config : permission.statement_id => permission
} : {}
principal = each.value.account_id
statement_id = each.value.statement_id
event_bus_name = lookup(each.value, aws_cloudwatch_event_bus.this[0].name, null) == null ? aws_cloudwatch_event_bus.this[0].name : null
}

48
outputs.tf Normal file
View file

@ -0,0 +1,48 @@
# EventBridge Bus
output "this_eventbridge_bus_name" {
description = "The EventBridge Bus Name"
value = var.bus_name
}
output "this_eventbridge_bus_arn" {
description = "The EventBridge Bus Arn"
value = element(concat(aws_cloudwatch_event_bus.this.*.arn, [""]), 0)
}
# EventBridge Archive
output "this_eventbridge_archive_arns" {
description = "The EventBridge Archive Arns created"
value = { for v in aws_cloudwatch_event_archive.this : v.name => v.arn }
}
# EventBridge Permission
output "this_eventbridge_permission_ids" {
description = "The EventBridge Permission Arns created"
value = { for k, v in aws_cloudwatch_event_permission.this : k => v.id }
}
# EventBridge Rule
output "this_eventbridge_rule_ids" {
description = "The EventBridge Rule IDs created"
value = {
for p in sort(keys(var.rules)) : p => aws_cloudwatch_event_rule.this[p].id
}
}
output "this_eventbridge_rule_arns" {
description = "The EventBridge Rule ARNs created"
value = {
for p in sort(keys(var.rules)) : p => aws_cloudwatch_event_rule.this[p].arn
}
}
# IAM Role
output "eventbridge_role_arn" {
description = "The ARN of the IAM role created for EventBridge"
value = element(concat(aws_iam_role.eventbridge.*.arn, [""]), 0)
}
output "eventbridge_role_name" {
description = "The name of the IAM role created for EventBridge"
value = element(concat(aws_iam_role.eventbridge.*.name, [""]), 0)
}

293
variables.tf Normal file
View file

@ -0,0 +1,293 @@
variable "bus_name" {
description = "A unique name for your EventBridge Bus"
type = string
default = ""
}
variable "rules" {
description = "A map of objects with EventBridge Rule definitions."
type = map(any)
default = {}
}
variable "targets" {
description = "A Map of objects with EventBridge Target definitions."
type = any
default = {}
}
variable "archive_config" {
description = "A list of objects with the EventBridge Archive definitions."
type = list(any)
default = []
}
variable "permission_config" {
description = "A list of objects with EventBridge Permission definitions."
type = list(any)
default = []
}
variable "tags" {
description = "A map of tags to assign to resources."
type = map(string)
default = {}
}
variable "create" {
description = "Controls whether resources should be created"
type = bool
default = true
}
variable "create_role" {
description = "Controls whether IAM role for Lambda Function should be created"
type = bool
default = true
}
variable "create_bus" {
description = "Controls whether EventBridge Bus resource should be created"
type = bool
default = true
}
variable "create_rules" {
description = "Controls whether EventBridge Rule resources should be created"
type = bool
default = true
}
variable "create_targets" {
description = "Controls whether EventBridge Target resources should be created"
type = bool
default = true
}
variable "create_permissions" {
description = "Controls whether EventBridge Permission resources should be created"
type = bool
default = true
}
variable "create_archives" {
description = "Controls whether EventBridge Archive resources should be created"
type = bool
default = false
}
######
# IAM
######
variable "role_name" {
description = "Name of IAM role to use for Lambda Function"
type = string
default = null
}
variable "role_description" {
description = "Description of IAM role to use for Lambda Function"
type = string
default = null
}
variable "role_path" {
description = "Path of IAM role to use for Lambda Function"
type = string
default = null
}
variable "role_force_detach_policies" {
description = "Specifies to force detaching any policies the IAM role has before destroying it."
type = bool
default = true
}
variable "role_permissions_boundary" {
description = "The ARN of the policy that is used to set the permissions boundary for the IAM role used by Lambda Function"
type = string
default = null
}
variable "role_tags" {
description = "A map of tags to assign to IAM role"
type = map(string)
default = {}
}
###########
# Policies
###########
variable "attach_kinesis_policy" {
description = "Controls whether the Kinesis policy should be added to IAM role for EventBridge Target"
type = bool
default = false
}
variable "attach_kinesis_firehose_policy" {
description = "Controls whether the Kinesis Firehose policy should be added to IAM role for EventBridge Target"
type = bool
default = false
}
variable "attach_sqs_policy" {
description = "Controls whether the SQS policy should be added to IAM role for EventBridge Target"
type = bool
default = false
}
variable "attach_ecs_policy" {
description = "Controls whether the ECS policy should be added to IAM role for EventBridge Target"
type = bool
default = false
}
variable "attach_lambda_policy" {
description = "Controls whether the Lambda Function policy should be added to IAM role for EventBridge Target"
type = bool
default = false
}
variable "attach_sfn_policy" {
description = "Controls whether the StepFunction policy should be added to IAM role for EventBridge Target"
type = bool
default = false
}
variable "attach_cloudwatch_policy" {
description = "Controls whether the Cloudwatch policy should be added to IAM role for EventBridge Target"
type = bool
default = false
}
variable "attach_tracing_policy" {
description = "Controls whether X-Ray tracing policy should be added to IAM role for EventBridge"
type = bool
default = false
}
variable "kinesis_target_arns" {
description = "The Amazon Resource Name (ARN) of the Kinesis Streams you want to use as EventBridge targets"
type = list(string)
default = []
}
variable "kinesis_firehose_target_arns" {
description = "The Amazon Resource Name (ARN) of the Kinesis Firehose Delivery Streams you want to use as EventBridge targets"
type = list(string)
default = []
}
variable "sqs_target_arns" {
description = "The Amazon Resource Name (ARN) of the AWS SQS Queues you want to use as EventBridge targets"
type = list(string)
default = []
}
variable "ecs_target_arns" {
description = "The Amazon Resource Name (ARN) of the AWS ECS Tasks you want to use as EventBridge targets"
type = list(string)
default = []
}
variable "lambda_target_arns" {
description = "The Amazon Resource Name (ARN) of the Lambda Functions you want to use as EventBridge targets"
type = list(string)
default = []
}
variable "sfn_target_arns" {
description = "The Amazon Resource Name (ARN) of the StepFunctions you want to use as EventBridge targets"
type = list(string)
default = []
}
variable "cloudwatch_target_arns" {
description = "The Amazon Resource Name (ARN) of the Cloudwatch Log Streams you want to use as EventBridge targets"
type = list(string)
default = []
}
##########################
# Various custom policies
##########################
variable "attach_policy_json" {
description = "Controls whether policy_json should be added to IAM role"
type = bool
default = false
}
variable "attach_policy_jsons" {
description = "Controls whether policy_jsons should be added to IAM role"
type = bool
default = false
}
variable "attach_policy" {
description = "Controls whether policy should be added to IAM role"
type = bool
default = false
}
variable "attach_policies" {
description = "Controls whether list of policies should be added to IAM role"
type = bool
default = false
}
variable "number_of_policy_jsons" {
description = "Number of policies JSON to attach to IAM role"
type = number
default = 0
}
variable "number_of_policies" {
description = "Number of policies to attach to IAM role"
type = number
default = 0
}
variable "attach_policy_statements" {
description = "Controls whether policy_statements should be added to IAM role"
type = bool
default = false
}
variable "trusted_entities" {
description = "Step Function additional trusted entities for assuming roles (trust relationship)"
type = list(string)
default = []
}
variable "policy_json" {
description = "An additional policy document as JSON to attach to IAM role"
type = string
default = null
}
variable "policy_jsons" {
description = "List of additional policy documents as JSON to attach to IAM role"
type = list(string)
default = []
}
variable "policy" {
description = "An additional policy document ARN to attach to IAM role"
type = string
default = null
}
variable "policies" {
description = "List of policy statements ARN to attach to IAM role"
type = list(string)
default = []
}
variable "policy_statements" {
description = "Map of dynamic policy statements to attach to IAM role"
type = any
default = {}
}

7
versions.tf Normal file
View file

@ -0,0 +1,7 @@
terraform {
required_version = ">= 0.12.26"
required_providers {
aws = ">= 3.19"
}
}