From 48eeb94c65b8519c3a436a90a41ad6008135fa87 Mon Sep 17 00:00:00 2001
From: Sven Lito <57947418+svenlito@users.noreply.github.com>
Date: Mon, 22 Mar 2021 23:15:02 +0700
Subject: [PATCH] feat: first commit (#1)

---
 .chglog/CHANGELOG.tpl.md                      | 111 +++++
 .chglog/config.yml                            |  11 +
 .editorconfig                                 |  32 ++
 .github/workflows/pre-commit.yml              | 102 +++++
 .gitignore                                    |  32 ++
 .pre-commit-config.yaml                       |  27 ++
 CHANGELOG.md                                  |   0
 LICENSE                                       |  13 +
 Makefile                                      |   7 +
 README.md                                     | 309 ++++++++++++-
 examples/api-gateway-event-source/README.md   |  16 +
 examples/api-gateway-event-source/main.tf     | 158 +++++++
 examples/api-gateway-event-source/outputs.tf  |  28 ++
 .../sample-order-data.json                    |  39 ++
 .../api-gateway-event-source/variables.tf     |   0
 examples/cloudwatch-target/README.md          |   0
 examples/cloudwatch-target/main.tf            |  68 +++
 examples/cloudwatch-target/outputs.tf         |   5 +
 examples/cloudwatch-target/variables.tf       |   0
 examples/complete/README.md                   |  15 +
 examples/complete/main.tf                     | 221 ++++++++++
 examples/complete/outputs.tf                  |  14 +
 examples/complete/variables.tf                |   0
 examples/simple/README.md                     |  16 +
 examples/simple/main.tf                       |  34 ++
 examples/simple/outputs.tf                    |   5 +
 examples/simple/variables.tf                  |   0
 examples/sqs-target/README.md                 |  17 +
 examples/sqs-target/main.tf                   | 115 +++++
 examples/sqs-target/outputs.tf                |  14 +
 examples/sqs-target/variables.tf              |   0
 examples/step-function-target/README.md       |   0
 examples/step-function-target/main.tf         |  79 ++++
 examples/step-function-target/outputs.tf      |   5 +
 examples/step-function-target/sfn.asl.yaml    |  12 +
 examples/step-function-target/variables.tf    |   0
 examples/transform-input/README.md            |  17 +
 examples/transform-input/main.tf              |  84 ++++
 examples/transform-input/outputs.tf           |   5 +
 examples/transform-input/variables.tf         |   0
 examples/with-archive/README.md               |  16 +
 examples/with-archive/main.tf                 | 100 +++++
 examples/with-archive/outputs.tf              |  10 +
 examples/with-archive/variables.tf            |   0
 examples/with-permissions/README.md           |  16 +
 examples/with-permissions/main.tf             |  50 +++
 examples/with-permissions/outputs.tf          |   9 +
 examples/with-permissions/variables.tf        |   0
 iam.tf                                        | 408 ++++++++++++++++++
 main.tf                                       | 166 +++++++
 outputs.tf                                    |  48 +++
 variables.tf                                  | 293 +++++++++++++
 versions.tf                                   |   7 +
 53 files changed, 2733 insertions(+), 1 deletion(-)
 create mode 100644 .chglog/CHANGELOG.tpl.md
 create mode 100644 .chglog/config.yml
 create mode 100644 .editorconfig
 create mode 100644 .github/workflows/pre-commit.yml
 create mode 100644 .gitignore
 create mode 100644 .pre-commit-config.yaml
 create mode 100644 CHANGELOG.md
 create mode 100644 LICENSE
 create mode 100644 Makefile
 create mode 100644 examples/api-gateway-event-source/README.md
 create mode 100644 examples/api-gateway-event-source/main.tf
 create mode 100644 examples/api-gateway-event-source/outputs.tf
 create mode 100644 examples/api-gateway-event-source/sample-order-data.json
 create mode 100644 examples/api-gateway-event-source/variables.tf
 create mode 100644 examples/cloudwatch-target/README.md
 create mode 100644 examples/cloudwatch-target/main.tf
 create mode 100644 examples/cloudwatch-target/outputs.tf
 create mode 100644 examples/cloudwatch-target/variables.tf
 create mode 100644 examples/complete/README.md
 create mode 100644 examples/complete/main.tf
 create mode 100644 examples/complete/outputs.tf
 create mode 100644 examples/complete/variables.tf
 create mode 100644 examples/simple/README.md
 create mode 100644 examples/simple/main.tf
 create mode 100644 examples/simple/outputs.tf
 create mode 100644 examples/simple/variables.tf
 create mode 100644 examples/sqs-target/README.md
 create mode 100644 examples/sqs-target/main.tf
 create mode 100644 examples/sqs-target/outputs.tf
 create mode 100644 examples/sqs-target/variables.tf
 create mode 100644 examples/step-function-target/README.md
 create mode 100644 examples/step-function-target/main.tf
 create mode 100644 examples/step-function-target/outputs.tf
 create mode 100644 examples/step-function-target/sfn.asl.yaml
 create mode 100644 examples/step-function-target/variables.tf
 create mode 100644 examples/transform-input/README.md
 create mode 100644 examples/transform-input/main.tf
 create mode 100644 examples/transform-input/outputs.tf
 create mode 100644 examples/transform-input/variables.tf
 create mode 100644 examples/with-archive/README.md
 create mode 100644 examples/with-archive/main.tf
 create mode 100644 examples/with-archive/outputs.tf
 create mode 100644 examples/with-archive/variables.tf
 create mode 100644 examples/with-permissions/README.md
 create mode 100644 examples/with-permissions/main.tf
 create mode 100644 examples/with-permissions/outputs.tf
 create mode 100644 examples/with-permissions/variables.tf
 create mode 100644 iam.tf
 create mode 100644 main.tf
 create mode 100644 outputs.tf
 create mode 100644 variables.tf
 create mode 100644 versions.tf

diff --git a/.chglog/CHANGELOG.tpl.md b/.chglog/CHANGELOG.tpl.md
new file mode 100644
index 0000000..687d702
--- /dev/null
+++ b/.chglog/CHANGELOG.tpl.md
@@ -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 -}}
diff --git a/.chglog/config.yml b/.chglog/config.yml
new file mode 100644
index 0000000..4f6bab9
--- /dev/null
+++ b/.chglog/config.yml
@@ -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
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..069c4d4
--- /dev/null
+++ b/.editorconfig
@@ -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
diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml
new file mode 100644
index 0000000..2be2f5d
--- /dev/null
+++ b/.github/workflows/pre-commit.yml
@@ -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
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..627f068
--- /dev/null
+++ b/.gitignore
@@ -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
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..ed7b682
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -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
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..e69de29
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..fe36d3a
--- /dev/null
+++ b/LICENSE
@@ -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.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..558dac5
--- /dev/null
+++ b/Makefile
@@ -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
diff --git a/README.md b/README.md
index 7718812..96bdc2b 100644
--- a/README.md
+++ b/README.md
@@ -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.
diff --git a/examples/api-gateway-event-source/README.md b/examples/api-gateway-event-source/README.md
new file mode 100644
index 0000000..39ae696
--- /dev/null
+++ b/examples/api-gateway-event-source/README.md
@@ -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.
+
diff --git a/examples/api-gateway-event-source/main.tf b/examples/api-gateway-event-source/main.tf
new file mode 100644
index 0000000..8e939ee
--- /dev/null
+++ b/examples/api-gateway-event-source/main.tf
@@ -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]
+  }
+}
diff --git a/examples/api-gateway-event-source/outputs.tf b/examples/api-gateway-event-source/outputs.tf
new file mode 100644
index 0000000..10f1f4e
--- /dev/null
+++ b/examples/api-gateway-event-source/outputs.tf
@@ -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
+}
diff --git a/examples/api-gateway-event-source/sample-order-data.json b/examples/api-gateway-event-source/sample-order-data.json
new file mode 100644
index 0000000..4de316c
--- /dev/null
+++ b/examples/api-gateway-event-source/sample-order-data.json
@@ -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"
+          }
+        }
+      ]
+    }
+  }
+}
diff --git a/examples/api-gateway-event-source/variables.tf b/examples/api-gateway-event-source/variables.tf
new file mode 100644
index 0000000..e69de29
diff --git a/examples/cloudwatch-target/README.md b/examples/cloudwatch-target/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/examples/cloudwatch-target/main.tf b/examples/cloudwatch-target/main.tf
new file mode 100644
index 0000000..3ba6bb5
--- /dev/null
+++ b/examples/cloudwatch-target/main.tf
@@ -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"
+  }
+}
+
diff --git a/examples/cloudwatch-target/outputs.tf b/examples/cloudwatch-target/outputs.tf
new file mode 100644
index 0000000..7a3ecdc
--- /dev/null
+++ b/examples/cloudwatch-target/outputs.tf
@@ -0,0 +1,5 @@
+output "eventbridge_bus_arn" {
+  description = "The EventBridge Bus ARN"
+  value       = module.eventbridge.this_eventbridge_bus_arn
+}
+
diff --git a/examples/cloudwatch-target/variables.tf b/examples/cloudwatch-target/variables.tf
new file mode 100644
index 0000000..e69de29
diff --git a/examples/complete/README.md b/examples/complete/README.md
new file mode 100644
index 0000000..9c16b08
--- /dev/null
+++ b/examples/complete/README.md
@@ -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.
diff --git a/examples/complete/main.tf b/examples/complete/main.tf
new file mode 100644
index 0000000..6b0f193
--- /dev/null
+++ b/examples/complete/main.tf
@@ -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"
+  }
+}
+
diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf
new file mode 100644
index 0000000..4b50256
--- /dev/null
+++ b/examples/complete/outputs.tf
@@ -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
+}
diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf
new file mode 100644
index 0000000..e69de29
diff --git a/examples/simple/README.md b/examples/simple/README.md
new file mode 100644
index 0000000..1d4cc2a
--- /dev/null
+++ b/examples/simple/README.md
@@ -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.
+
diff --git a/examples/simple/main.tf b/examples/simple/main.tf
new file mode 100644
index 0000000..e2dfbb2
--- /dev/null
+++ b/examples/simple/main.tf
@@ -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"
+  }
+}
+
diff --git a/examples/simple/outputs.tf b/examples/simple/outputs.tf
new file mode 100644
index 0000000..7a3ecdc
--- /dev/null
+++ b/examples/simple/outputs.tf
@@ -0,0 +1,5 @@
+output "eventbridge_bus_arn" {
+  description = "The EventBridge Bus ARN"
+  value       = module.eventbridge.this_eventbridge_bus_arn
+}
+
diff --git a/examples/simple/variables.tf b/examples/simple/variables.tf
new file mode 100644
index 0000000..e69de29
diff --git a/examples/sqs-target/README.md b/examples/sqs-target/README.md
new file mode 100644
index 0000000..96fcf85
--- /dev/null
+++ b/examples/sqs-target/README.md
@@ -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.
+
+
diff --git a/examples/sqs-target/main.tf b/examples/sqs-target/main.tf
new file mode 100644
index 0000000..a5afedb
--- /dev/null
+++ b/examples/sqs-target/main.tf
@@ -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
+    ]
+  }
+}
+
diff --git a/examples/sqs-target/outputs.tf b/examples/sqs-target/outputs.tf
new file mode 100644
index 0000000..4b50256
--- /dev/null
+++ b/examples/sqs-target/outputs.tf
@@ -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
+}
diff --git a/examples/sqs-target/variables.tf b/examples/sqs-target/variables.tf
new file mode 100644
index 0000000..e69de29
diff --git a/examples/step-function-target/README.md b/examples/step-function-target/README.md
new file mode 100644
index 0000000..e69de29
diff --git a/examples/step-function-target/main.tf b/examples/step-function-target/main.tf
new file mode 100644
index 0000000..dc694b0
--- /dev/null
+++ b/examples/step-function-target/main.tf
@@ -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"
+  }
+}
+
diff --git a/examples/step-function-target/outputs.tf b/examples/step-function-target/outputs.tf
new file mode 100644
index 0000000..7a3ecdc
--- /dev/null
+++ b/examples/step-function-target/outputs.tf
@@ -0,0 +1,5 @@
+output "eventbridge_bus_arn" {
+  description = "The EventBridge Bus ARN"
+  value       = module.eventbridge.this_eventbridge_bus_arn
+}
+
diff --git a/examples/step-function-target/sfn.asl.yaml b/examples/step-function-target/sfn.asl.yaml
new file mode 100644
index 0000000..dfc0c19
--- /dev/null
+++ b/examples/step-function-target/sfn.asl.yaml
@@ -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
diff --git a/examples/step-function-target/variables.tf b/examples/step-function-target/variables.tf
new file mode 100644
index 0000000..e69de29
diff --git a/examples/transform-input/README.md b/examples/transform-input/README.md
new file mode 100644
index 0000000..2fb4520
--- /dev/null
+++ b/examples/transform-input/README.md
@@ -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.
+
+
diff --git a/examples/transform-input/main.tf b/examples/transform-input/main.tf
new file mode 100644
index 0000000..6c6547f
--- /dev/null
+++ b/examples/transform-input/main.tf
@@ -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]
+  }
+}
diff --git a/examples/transform-input/outputs.tf b/examples/transform-input/outputs.tf
new file mode 100644
index 0000000..7a3ecdc
--- /dev/null
+++ b/examples/transform-input/outputs.tf
@@ -0,0 +1,5 @@
+output "eventbridge_bus_arn" {
+  description = "The EventBridge Bus ARN"
+  value       = module.eventbridge.this_eventbridge_bus_arn
+}
+
diff --git a/examples/transform-input/variables.tf b/examples/transform-input/variables.tf
new file mode 100644
index 0000000..e69de29
diff --git a/examples/with-archive/README.md b/examples/with-archive/README.md
new file mode 100644
index 0000000..1d4cc2a
--- /dev/null
+++ b/examples/with-archive/README.md
@@ -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.
+
diff --git a/examples/with-archive/main.tf b/examples/with-archive/main.tf
new file mode 100644
index 0000000..2388b31
--- /dev/null
+++ b/examples/with-archive/main.tf
@@ -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"
+}
+
diff --git a/examples/with-archive/outputs.tf b/examples/with-archive/outputs.tf
new file mode 100644
index 0000000..864bf8d
--- /dev/null
+++ b/examples/with-archive/outputs.tf
@@ -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
+}
+
diff --git a/examples/with-archive/variables.tf b/examples/with-archive/variables.tf
new file mode 100644
index 0000000..e69de29
diff --git a/examples/with-permissions/README.md b/examples/with-permissions/README.md
new file mode 100644
index 0000000..1d4cc2a
--- /dev/null
+++ b/examples/with-permissions/README.md
@@ -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.
+
diff --git a/examples/with-permissions/main.tf b/examples/with-permissions/main.tf
new file mode 100644
index 0000000..a2f27b9
--- /dev/null
+++ b/examples/with-permissions/main.tf
@@ -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
+}
diff --git a/examples/with-permissions/outputs.tf b/examples/with-permissions/outputs.tf
new file mode 100644
index 0000000..fa74977
--- /dev/null
+++ b/examples/with-permissions/outputs.tf
@@ -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
+}
diff --git a/examples/with-permissions/variables.tf b/examples/with-permissions/variables.tf
new file mode 100644
index 0000000..e69de29
diff --git a/iam.tf b/iam.tf
new file mode 100644
index 0000000..381b1ff
--- /dev/null
+++ b/iam.tf
@@ -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
+}
diff --git a/main.tf b/main.tf
new file mode 100644
index 0000000..81ebcb7
--- /dev/null
+++ b/main.tf
@@ -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
+}
diff --git a/outputs.tf b/outputs.tf
new file mode 100644
index 0000000..568855d
--- /dev/null
+++ b/outputs.tf
@@ -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)
+}
diff --git a/variables.tf b/variables.tf
new file mode 100644
index 0000000..42ba02d
--- /dev/null
+++ b/variables.tf
@@ -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     = {}
+}
diff --git a/versions.tf b/versions.tf
new file mode 100644
index 0000000..2c2f74f
--- /dev/null
+++ b/versions.tf
@@ -0,0 +1,7 @@
+terraform {
+  required_version = ">= 0.12.26"
+
+  required_providers {
+    aws = ">= 3.19"
+  }
+}