├── .editorconfig ├── .github ├── .gitkeep └── workflows │ ├── lock.yml │ ├── pr-title.yml │ ├── pre-commit.yml │ ├── release.yml │ └── stale-actions.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── .releaserc.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── examples ├── README.md ├── complete │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf └── separate │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf ├── main.tf ├── modules ├── firewall │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf ├── policy │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf └── rule-group │ ├── README.md │ ├── main.tf │ ├── outputs.tf │ ├── variables.tf │ └── versions.tf ├── outputs.tf ├── variables.tf ├── versions.tf └── wrappers ├── README.md ├── firewall ├── README.md ├── main.tf ├── outputs.tf ├── variables.tf └── versions.tf ├── main.tf ├── outputs.tf ├── policy ├── README.md ├── main.tf ├── outputs.tf ├── variables.tf └── versions.tf ├── rule-group ├── README.md ├── main.tf ├── outputs.tf ├── variables.tf └── versions.tf ├── variables.tf └── versions.tf /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | # Uses editorconfig to maintain consistent coding styles 3 | 4 | # top-most EditorConfig file 5 | root = true 6 | 7 | # Unix-style newlines with a newline ending every file 8 | [*] 9 | charset = utf-8 10 | end_of_line = lf 11 | indent_size = 2 12 | indent_style = space 13 | insert_final_newline = true 14 | max_line_length = 80 15 | trim_trailing_whitespace = true 16 | 17 | [*.{tf,tfvars}] 18 | indent_size = 2 19 | indent_style = space 20 | 21 | [*.md] 22 | max_line_length = 0 23 | trim_trailing_whitespace = false 24 | 25 | [Makefile] 26 | tab_width = 2 27 | indent_style = tab 28 | 29 | [COMMIT_EDITMSG] 30 | max_line_length = 0 31 | -------------------------------------------------------------------------------- /.github/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-network-firewall/f63f12514ad0e5f216c1690f154cff6b1c111e08/.github/.gitkeep -------------------------------------------------------------------------------- /.github/workflows/lock.yml: -------------------------------------------------------------------------------- 1 | name: 'Lock Threads' 2 | 3 | on: 4 | schedule: 5 | - cron: '50 1 * * *' 6 | 7 | jobs: 8 | lock: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: dessant/lock-threads@v5 12 | with: 13 | github-token: ${{ secrets.GITHUB_TOKEN }} 14 | issue-comment: > 15 | I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues. 16 | If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. 17 | issue-inactive-days: '30' 18 | pr-comment: > 19 | I'm going to lock this pull request because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues. 20 | If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. 21 | pr-inactive-days: '30' 22 | -------------------------------------------------------------------------------- /.github/workflows/pr-title.yml: -------------------------------------------------------------------------------- 1 | name: 'Validate PR title' 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - edited 8 | - synchronize 9 | 10 | jobs: 11 | main: 12 | name: Validate PR title 13 | runs-on: ubuntu-latest 14 | steps: 15 | # Please look up the latest version from 16 | # https://github.com/amannn/action-semantic-pull-request/releases 17 | - uses: amannn/action-semantic-pull-request@v5.5.3 18 | env: 19 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 20 | with: 21 | # Configure which types are allowed. 22 | # Default: https://github.com/commitizen/conventional-commit-types 23 | types: | 24 | fix 25 | feat 26 | docs 27 | ci 28 | chore 29 | # Configure that a scope must always be provided. 30 | requireScope: false 31 | # Configure additional validation for the subject based on a regex. 32 | # This example ensures the subject starts with an uppercase character. 33 | subjectPattern: ^[A-Z].+$ 34 | # If `subjectPattern` is configured, you can use this property to override 35 | # the default error message that is shown when the pattern doesn't match. 36 | # The variables `subject` and `title` can be used within the message. 37 | subjectPatternError: | 38 | The subject "{subject}" found in the pull request title "{title}" 39 | didn't match the configured pattern. Please ensure that the subject 40 | starts with an uppercase character. 41 | # For work-in-progress PRs you can typically use draft pull requests 42 | # from Github. However, private repositories on the free plan don't have 43 | # this option and therefore this action allows you to opt-in to using the 44 | # special "[WIP]" prefix to indicate this state. This will avoid the 45 | # validation of the PR title and the pull request checks remain pending. 46 | # Note that a second check will be reported if this is enabled. 47 | wip: true 48 | # When using "Squash and merge" on a PR with only one commit, GitHub 49 | # will suggest using that commit message instead of the PR title for the 50 | # merge commit, and it's easy to commit this by mistake. Enable this option 51 | # to also validate the commit message for one commit PRs. 52 | validateSingleCommit: false 53 | -------------------------------------------------------------------------------- /.github/workflows/pre-commit.yml: -------------------------------------------------------------------------------- 1 | name: Pre-Commit 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | - master 8 | 9 | env: 10 | TERRAFORM_DOCS_VERSION: v0.19.0 11 | TFLINT_VERSION: v0.53.0 12 | 13 | jobs: 14 | collectInputs: 15 | name: Collect workflow inputs 16 | runs-on: ubuntu-latest 17 | outputs: 18 | directories: ${{ steps.dirs.outputs.directories }} 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v4 22 | 23 | - name: Get root directories 24 | id: dirs 25 | uses: clowdhaus/terraform-composite-actions/directories@v1.9.0 26 | 27 | preCommitMinVersions: 28 | name: Min TF pre-commit 29 | needs: collectInputs 30 | runs-on: ubuntu-latest 31 | strategy: 32 | matrix: 33 | directory: ${{ fromJson(needs.collectInputs.outputs.directories) }} 34 | steps: 35 | # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449 36 | - name: Delete huge unnecessary tools folder 37 | run: | 38 | rm -rf /opt/hostedtoolcache/CodeQL 39 | rm -rf /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk 40 | rm -rf /opt/hostedtoolcache/Ruby 41 | rm -rf /opt/hostedtoolcache/go 42 | 43 | - name: Checkout 44 | uses: actions/checkout@v4 45 | 46 | - name: Terraform min/max versions 47 | id: minMax 48 | uses: clowdhaus/terraform-min-max@v1.3.1 49 | with: 50 | directory: ${{ matrix.directory }} 51 | 52 | - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }} 53 | # Run only validate pre-commit check on min version supported 54 | if: ${{ matrix.directory != '.' }} 55 | uses: clowdhaus/terraform-composite-actions/pre-commit@v1.11.1 56 | with: 57 | terraform-version: ${{ steps.minMax.outputs.minVersion }} 58 | tflint-version: ${{ env.TFLINT_VERSION }} 59 | args: 'terraform_validate --color=always --show-diff-on-failure --files ${{ matrix.directory }}/*' 60 | 61 | - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }} 62 | # Run only validate pre-commit check on min version supported 63 | if: ${{ matrix.directory == '.' }} 64 | uses: clowdhaus/terraform-composite-actions/pre-commit@v1.11.1 65 | with: 66 | terraform-version: ${{ steps.minMax.outputs.minVersion }} 67 | tflint-version: ${{ env.TFLINT_VERSION }} 68 | args: 'terraform_validate --color=always --show-diff-on-failure --files $(ls *.tf)' 69 | 70 | preCommitMaxVersion: 71 | name: Max TF pre-commit 72 | runs-on: ubuntu-latest 73 | needs: collectInputs 74 | steps: 75 | # https://github.com/orgs/community/discussions/25678#discussioncomment-5242449 76 | - name: Delete huge unnecessary tools folder 77 | run: | 78 | rm -rf /opt/hostedtoolcache/CodeQL 79 | rm -rf /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk 80 | rm -rf /opt/hostedtoolcache/Ruby 81 | rm -rf /opt/hostedtoolcache/go 82 | 83 | - name: Checkout 84 | uses: actions/checkout@v4 85 | with: 86 | ref: ${{ github.event.pull_request.head.ref }} 87 | repository: ${{github.event.pull_request.head.repo.full_name}} 88 | 89 | - name: Terraform min/max versions 90 | id: minMax 91 | uses: clowdhaus/terraform-min-max@v1.3.1 92 | 93 | - name: Pre-commit Terraform ${{ steps.minMax.outputs.maxVersion }} 94 | uses: clowdhaus/terraform-composite-actions/pre-commit@v1.11.1 95 | with: 96 | terraform-version: ${{ steps.minMax.outputs.maxVersion }} 97 | tflint-version: ${{ env.TFLINT_VERSION }} 98 | terraform-docs-version: ${{ env.TERRAFORM_DOCS_VERSION }} 99 | install-hcledit: true 100 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | - master 9 | paths: 10 | - '**/*.tpl' 11 | - '**/*.py' 12 | - '**/*.tf' 13 | - '.github/workflows/release.yml' 14 | 15 | jobs: 16 | release: 17 | name: Release 18 | runs-on: ubuntu-latest 19 | # Skip running release workflow on forks 20 | if: github.repository_owner == 'terraform-aws-modules' 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v4 24 | with: 25 | persist-credentials: false 26 | fetch-depth: 0 27 | 28 | - name: Release 29 | uses: cycjimmy/semantic-release-action@v4 30 | with: 31 | semantic_version: 23.0.2 32 | extra_plugins: | 33 | @semantic-release/changelog@6.0.3 34 | @semantic-release/git@10.0.1 35 | conventional-changelog-conventionalcommits@7.0.2 36 | env: 37 | GITHUB_TOKEN: ${{ secrets.SEMANTIC_RELEASE_TOKEN }} 38 | -------------------------------------------------------------------------------- /.github/workflows/stale-actions.yaml: -------------------------------------------------------------------------------- 1 | name: 'Mark or close stale issues and PRs' 2 | on: 3 | schedule: 4 | - cron: '0 0 * * *' 5 | 6 | jobs: 7 | stale: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/stale@v9 11 | with: 12 | repo-token: ${{ secrets.GITHUB_TOKEN }} 13 | # Staling issues and PR's 14 | days-before-stale: 30 15 | stale-issue-label: stale 16 | stale-pr-label: stale 17 | stale-issue-message: | 18 | This issue has been automatically marked as stale because it has been open 30 days 19 | with no activity. Remove stale label or comment or this issue will be closed in 10 days 20 | stale-pr-message: | 21 | This PR has been automatically marked as stale because it has been open 30 days 22 | with no activity. Remove stale label or comment or this PR will be closed in 10 days 23 | # Not stale if have this labels or part of milestone 24 | exempt-issue-labels: bug,wip,on-hold 25 | exempt-pr-labels: bug,wip,on-hold 26 | exempt-all-milestones: true 27 | # Close issue operations 28 | # Label will be automatically removed if the issues are no longer closed nor locked. 29 | days-before-close: 10 30 | delete-branch: true 31 | close-issue-message: This issue was automatically closed because of stale in 10 days 32 | close-pr-message: This PR was automatically closed because of stale in 10 days 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Local .terraform directories 2 | **/.terraform/* 3 | 4 | # .tfstate files 5 | *.tfstate 6 | *.tfstate.* 7 | 8 | # terraform lockfile 9 | .terraform.lock.hcl 10 | 11 | # Crash log files 12 | crash.log 13 | 14 | # Exclude all .tfvars files, which are likely to contain sentitive data, such as 15 | # password, private keys, and other secrets. These should not be part of version 16 | # control as they are data points which are potentially sensitive and subject 17 | # to change depending on the environment. 18 | # 19 | *.tfvars 20 | 21 | # Ignore override files as they are usually used to override resources locally and so 22 | # are not checked in 23 | override.tf 24 | override.tf.json 25 | *_override.tf 26 | *_override.tf.json 27 | 28 | # Include override files you do wish to add to version control using negated pattern 29 | # 30 | # !example_override.tf 31 | 32 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 33 | # example: *tfplan* 34 | 35 | # Ignore CLI configuration files 36 | .terraformrc 37 | terraform.rc 38 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/antonbabenko/pre-commit-terraform 3 | rev: v1.96.1 4 | hooks: 5 | - id: terraform_fmt 6 | - id: terraform_wrapper_module_for_each 7 | - id: terraform_docs 8 | args: 9 | - '--args=--lockfile=false' 10 | - id: terraform_tflint 11 | args: 12 | - '--args=--only=terraform_deprecated_interpolation' 13 | - '--args=--only=terraform_deprecated_index' 14 | - '--args=--only=terraform_unused_declarations' 15 | - '--args=--only=terraform_comment_syntax' 16 | - '--args=--only=terraform_documented_outputs' 17 | - '--args=--only=terraform_documented_variables' 18 | - '--args=--only=terraform_typed_variables' 19 | - '--args=--only=terraform_module_pinned_source' 20 | - '--args=--only=terraform_naming_convention' 21 | - '--args=--only=terraform_required_version' 22 | - '--args=--only=terraform_required_providers' 23 | - '--args=--only=terraform_standard_module_structure' 24 | - '--args=--only=terraform_workspace_remote' 25 | - id: terraform_validate 26 | - repo: https://github.com/pre-commit/pre-commit-hooks 27 | rev: v5.0.0 28 | hooks: 29 | - id: check-merge-conflict 30 | - id: end-of-file-fixer 31 | - id: trailing-whitespace 32 | -------------------------------------------------------------------------------- /.releaserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "branches": [ 3 | "main", 4 | "master" 5 | ], 6 | "ci": false, 7 | "plugins": [ 8 | [ 9 | "@semantic-release/commit-analyzer", 10 | { 11 | "preset": "conventionalcommits" 12 | } 13 | ], 14 | [ 15 | "@semantic-release/release-notes-generator", 16 | { 17 | "preset": "conventionalcommits" 18 | } 19 | ], 20 | [ 21 | "@semantic-release/github", 22 | { 23 | "successComment": "This ${issue.pull_request ? 'PR is included' : 'issue has been resolved'} in version ${nextRelease.version} :tada:", 24 | "labels": false, 25 | "releasedLabels": false 26 | } 27 | ], 28 | [ 29 | "@semantic-release/changelog", 30 | { 31 | "changelogFile": "CHANGELOG.md", 32 | "changelogTitle": "# Changelog\n\nAll notable changes to this project will be documented in this file." 33 | } 34 | ], 35 | [ 36 | "@semantic-release/git", 37 | { 38 | "assets": [ 39 | "CHANGELOG.md" 40 | ], 41 | "message": "chore(release): version ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" 42 | } 43 | ] 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | ## [1.0.2](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/compare/v1.0.1...v1.0.2) (2024-10-11) 6 | 7 | 8 | ### Bug Fixes 9 | 10 | * Update CI workflow versions to latest ([#5](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/issues/5)) ([817cc97](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/commit/817cc977a01a522dda0d2fa6158e7dcb7813dced)) 11 | 12 | ## [1.0.1](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/compare/v1.0.0...v1.0.1) (2024-03-07) 13 | 14 | 15 | ### Bug Fixes 16 | 17 | * Update CI workflow versions to remove deprecated runtime warnings ([#2](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/issues/2)) ([933d856](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/commit/933d856f54fb6da2c4c3d0f940c93c5aac725de8)) 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AWS Network Firewall Terraform module 2 | 3 | Terraform module which creates AWS network firewall resources. 4 | 5 | [](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md) 6 | 7 | ## Usage 8 | 9 | This project supports creating resources through individual sub-modules for better support for RAM resource sharing, or through a single module that creates both the firewall and firewall policy resources. 10 | See the respective sub-module directory for more details and example usage. 11 | 12 | ```hcl 13 | module "network_firewall" { 14 | source = "terraform-aws-modules/network-firewall/aws" 15 | 16 | # Firewall 17 | name = "example" 18 | description = "Example network firewall" 19 | 20 | vpc_id = "vpc-1234556abcdef" 21 | subnet_mapping = { 22 | subnet1 = { 23 | subnet_id = "subnet-abcde012" 24 | ip_address_type = "IPV4" 25 | } 26 | subnet2 = { 27 | subnet_id = "subnet-bcde012a" 28 | ip_address_type = "IPV4" 29 | } 30 | subnet2 = { 31 | subnet_id = "subnet-fghi345a" 32 | ip_address_type = "IPV4" 33 | } 34 | } 35 | 36 | # Logging configuration 37 | create_logging_configuration = true 38 | logging_configuration_destination_config = [ 39 | { 40 | log_destination = { 41 | logGroup = "/aws/network-firewall/example" 42 | } 43 | log_destination_type = "CloudWatchLogs" 44 | log_type = "ALERT" 45 | }, 46 | { 47 | log_destination = { 48 | bucketName = "s3-example-bucket-firewall-flow-logs" 49 | prefix = "example" 50 | } 51 | log_destination_type = "S3" 52 | log_type = "FLOW" 53 | } 54 | ] 55 | 56 | # Policy 57 | policy_name = "example" 58 | policy_description = "Example network firewall policy" 59 | 60 | policy_stateful_rule_group_reference = { 61 | one = { 62 | priority = 0 63 | resource_arn = "arn:aws:network-firewall:us-east-1:1234567890:stateful-rulegroup/example" 64 | } 65 | } 66 | 67 | policy_stateless_default_actions = ["aws:pass"] 68 | policy_stateless_fragment_default_actions = ["aws:drop"] 69 | policy_stateless_rule_group_reference = { 70 | one = { 71 | priority = 0 72 | resource_arn = "arn:aws:network-firewall:us-east-1:1234567890:stateless-rulegroup/example" 73 | } 74 | } 75 | 76 | tags = { 77 | Terraform = "true" 78 | Environment = "dev" 79 | } 80 | } 81 | ``` 82 | 83 | 84 | ## Examples 85 | 86 | Examples codified under the [`examples`](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/tree/master/examples) are intended to give users references for how to use the module(s) as well as testing/validating changes to the source code of the module. If contributing to the project, please be sure to make any appropriate updates to the relevant examples to allow maintainers to test your changes and to keep the examples up to date for users. Thank you! 87 | 88 | - [Complete](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/tree/master/examples/complete) 89 | - [Separate](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/tree/master/examples/separate) 90 | 91 | 92 | ## Requirements 93 | 94 | | Name | Version | 95 | |------|---------| 96 | | [terraform](#requirement\_terraform) | >= 1.0 | 97 | 98 | ## Providers 99 | 100 | No providers. 101 | 102 | ## Modules 103 | 104 | | Name | Source | Version | 105 | |------|--------|---------| 106 | | [firewall](#module\_firewall) | ./modules/firewall | n/a | 107 | | [policy](#module\_policy) | ./modules/policy | n/a | 108 | 109 | ## Resources 110 | 111 | No resources. 112 | 113 | ## Inputs 114 | 115 | | Name | Description | Type | Default | Required | 116 | |------|-------------|------|---------|:--------:| 117 | | [create](#input\_create) | Controls if resources should be created | `bool` | `true` | no | 118 | | [create\_logging\_configuration](#input\_create\_logging\_configuration) | Controls if a Logging Configuration should be created | `bool` | `false` | no | 119 | | [create\_policy](#input\_create\_policy) | Controls if policy should be created | `bool` | `true` | no | 120 | | [create\_policy\_resource\_policy](#input\_create\_policy\_resource\_policy) | Controls if a resource policy should be created | `bool` | `false` | no | 121 | | [delete\_protection](#input\_delete\_protection) | A boolean flag indicating whether it is possible to delete the firewall. Defaults to `true` | `bool` | `true` | no | 122 | | [description](#input\_description) | A friendly description of the firewall | `string` | `""` | no | 123 | | [encryption\_configuration](#input\_encryption\_configuration) | KMS encryption configuration settings | `any` | `{}` | no | 124 | | [firewall\_policy\_arn](#input\_firewall\_policy\_arn) | The ARN of the Firewall Policy to use | `string` | `""` | no | 125 | | [firewall\_policy\_change\_protection](#input\_firewall\_policy\_change\_protection) | A boolean flag indicating whether it is possible to change the associated firewall policy. Defaults to `false` | `bool` | `null` | no | 126 | | [logging\_configuration\_destination\_config](#input\_logging\_configuration\_destination\_config) | A list of min 1, max 2 configuration blocks describing the destination for the logging configuration | `any` | `[]` | no | 127 | | [name](#input\_name) | A friendly name of the firewall | `string` | `""` | no | 128 | | [policy\_attach\_resource\_policy](#input\_policy\_attach\_resource\_policy) | Controls if a resource policy should be attached to the firewall policy | `bool` | `false` | no | 129 | | [policy\_description](#input\_policy\_description) | A friendly description of the firewall policy | `string` | `null` | no | 130 | | [policy\_encryption\_configuration](#input\_policy\_encryption\_configuration) | KMS encryption configuration settings | `any` | `{}` | no | 131 | | [policy\_name](#input\_policy\_name) | A friendly name of the firewall policy | `string` | `""` | no | 132 | | [policy\_ram\_resource\_associations](#input\_policy\_ram\_resource\_associations) | A map of RAM resource associations for the created firewall policy | `map(string)` | `{}` | no | 133 | | [policy\_resource\_policy](#input\_policy\_resource\_policy) | The policy JSON to use for the resource policy; required when `create_resource_policy` is `false` | `string` | `""` | no | 134 | | [policy\_resource\_policy\_actions](#input\_policy\_resource\_policy\_actions) | A list of IAM actions allowed in the resource policy | `list(string)` | `[]` | no | 135 | | [policy\_resource\_policy\_principals](#input\_policy\_resource\_policy\_principals) | A list of IAM principals allowed in the resource policy | `list(string)` | `[]` | no | 136 | | [policy\_stateful\_default\_actions](#input\_policy\_stateful\_default\_actions) | Set of actions to take on a packet if it does not match any stateful rules in the policy. This can only be specified if the policy has a `stateful_engine_options` block with a rule\_order value of `STRICT_ORDER`. You can specify one of either or neither values of `aws:drop_strict` or `aws:drop_established`, as well as any combination of `aws:alert_strict` and `aws:alert_established` | `list(string)` | `[]` | no | 137 | | [policy\_stateful\_engine\_options](#input\_policy\_stateful\_engine\_options) | A configuration block that defines options on how the policy handles stateful rules. See [Stateful Engine Options](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy#stateful-engine-options) for details | `any` | `{}` | no | 138 | | [policy\_stateful\_rule\_group\_reference](#input\_policy\_stateful\_rule\_group\_reference) | Set of configuration blocks containing references to the stateful rule groups that are used in the policy. See [Stateful Rule Group Reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy#stateful-rule-group-reference) for details | `any` | `{}` | no | 139 | | [policy\_stateless\_custom\_action](#input\_policy\_stateless\_custom\_action) | Set of configuration blocks describing the custom action definitions that are available for use in the firewall policy's `stateless_default_actions` | `any` | `{}` | no | 140 | | [policy\_stateless\_default\_actions](#input\_policy\_stateless\_default\_actions) | Set of actions to take on a packet if it does not match any of the stateless rules in the policy. You must specify one of the standard actions including: `aws:drop`, `aws:pass`, or `aws:forward_to_sfe` | `list(string)` |
[| no | 141 | | [policy\_stateless\_fragment\_default\_actions](#input\_policy\_stateless\_fragment\_default\_actions) | Set of actions to take on a fragmented packet if it does not match any of the stateless rules in the policy. You must specify one of the standard actions including: `aws:drop`, `aws:pass`, or `aws:forward_to_sfe` | `list(string)` |
"aws:pass"
]
[| no | 142 | | [policy\_stateless\_rule\_group\_reference](#input\_policy\_stateless\_rule\_group\_reference) | Set of configuration blocks containing references to the stateless rule groups that are used in the policy. See [Stateless Rule Group Reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy#stateless-rule-group-reference) for details | `any` | `{}` | no | 143 | | [policy\_tags](#input\_policy\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | 144 | | [subnet\_change\_protection](#input\_subnet\_change\_protection) | A boolean flag indicating whether it is possible to change the associated subnet(s). Defaults to `true` | `bool` | `true` | no | 145 | | [subnet\_mapping](#input\_subnet\_mapping) | Set of configuration blocks describing the public subnets. Each subnet must belong to a different Availability Zone in the VPC. AWS Network Firewall creates a firewall endpoint in each subnet | `any` | `{}` | no | 146 | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | 147 | | [vpc\_id](#input\_vpc\_id) | The unique identifier of the VPC where AWS Network Firewall should create the firewall | `string` | `""` | no | 148 | 149 | ## Outputs 150 | 151 | | Name | Description | 152 | |------|-------------| 153 | | [arn](#output\_arn) | The Amazon Resource Name (ARN) that identifies the firewall | 154 | | [id](#output\_id) | The Amazon Resource Name (ARN) that identifies the firewall | 155 | | [logging\_configuration\_id](#output\_logging\_configuration\_id) | The Amazon Resource Name (ARN) of the associated firewall | 156 | | [policy\_arn](#output\_policy\_arn) | The Amazon Resource Name (ARN) that identifies the firewall policy | 157 | | [policy\_id](#output\_policy\_id) | The Amazon Resource Name (ARN) that identifies the firewall policy | 158 | | [policy\_resource\_policy\_id](#output\_policy\_resource\_policy\_id) | The Amazon Resource Name (ARN) of the firewall policy associated with the resource policy | 159 | | [policy\_update\_token](#output\_policy\_update\_token) | A string token used when updating a firewall policy | 160 | | [status](#output\_status) | Nested list of information about the current status of the firewall | 161 | | [update\_token](#output\_update\_token) | A string token used when updating a firewall | 162 | 163 | 164 | ## License 165 | 166 | Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/blob/master/LICENSE). 167 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | Please note - the examples provided serve two primary means: 4 | 5 | 1. Show users working examples of the various ways in which the module can be configured and features supported 6 | 2. A means of testing/validating module changes 7 | 8 | Please do not mistake the examples provided as "best practices". It is up to users to consult the AWS service documentation for best practices, usage recommendations, etc. 9 | -------------------------------------------------------------------------------- /examples/complete/README.md: -------------------------------------------------------------------------------- 1 | # Complete AWS Network Firewall Example 2 | 3 | Configuration in this directory creates the following as separate module definitions: 4 | 5 | - AWS Network Firewall & Firewall Policy 6 | - AWS Network Firewall Rule Group 7 | 8 | ## Usage 9 | 10 | To run this example you need to execute: 11 | 12 | ```bash 13 | $ terraform init 14 | $ terraform plan 15 | $ terraform apply 16 | ``` 17 | 18 | Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources. 19 | 20 | 21 | ## Requirements 22 | 23 | | Name | Version | 24 | |------|---------| 25 | | [terraform](#requirement\_terraform) | >= 1.0 | 26 | | [aws](#requirement\_aws) | >= 5.2 | 27 | 28 | ## Providers 29 | 30 | | Name | Version | 31 | |------|---------| 32 | | [aws](#provider\_aws) | >= 5.2 | 33 | 34 | ## Modules 35 | 36 | | Name | Source | Version | 37 | |------|--------|---------| 38 | | [network\_firewall](#module\_network\_firewall) | ../.. | n/a | 39 | | [network\_firewall\_disabled](#module\_network\_firewall\_disabled) | ../.. | n/a | 40 | | [network\_firewall\_rule\_group\_stateful](#module\_network\_firewall\_rule\_group\_stateful) | ../../modules/rule-group | n/a | 41 | | [network\_firewall\_rule\_group\_stateless](#module\_network\_firewall\_rule\_group\_stateless) | ../../modules/rule-group | n/a | 42 | | [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | 43 | 44 | ## Resources 45 | 46 | | Name | Type | 47 | |------|------| 48 | | [aws_cloudwatch_log_group.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | 49 | | [aws_s3_bucket.network_firewall_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | 50 | | [aws_s3_bucket_policy.network_firewall_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | 51 | | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | 52 | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | 53 | 54 | ## Inputs 55 | 56 | No inputs. 57 | 58 | ## Outputs 59 | 60 | | Name | Description | 61 | |------|-------------| 62 | | [firewall\_arn](#output\_firewall\_arn) | The Amazon Resource Name (ARN) that identifies the firewall | 63 | | [firewall\_id](#output\_firewall\_id) | The Amazon Resource Name (ARN) that identifies the firewall | 64 | | [firewall\_logging\_configuration\_id](#output\_firewall\_logging\_configuration\_id) | The Amazon Resource Name (ARN) of the associated firewall | 65 | | [firewall\_policy\_arn](#output\_firewall\_policy\_arn) | The Amazon Resource Name (ARN) that identifies the firewall policy | 66 | | [firewall\_policy\_id](#output\_firewall\_policy\_id) | The Amazon Resource Name (ARN) that identifies the firewall policy | 67 | | [firewall\_policy\_resource\_policy\_id](#output\_firewall\_policy\_resource\_policy\_id) | The Amazon Resource Name (ARN) of the firewall policy associated with the resource policy | 68 | | [firewall\_policy\_update\_token](#output\_firewall\_policy\_update\_token) | A string token used when updating a firewall policy | 69 | | [firewall\_rule\_group\_stateful\_arn](#output\_firewall\_rule\_group\_stateful\_arn) | The Amazon Resource Name (ARN) that identifies the rule group | 70 | | [firewall\_rule\_group\_stateful\_id](#output\_firewall\_rule\_group\_stateful\_id) | The Amazon Resource Name (ARN) that identifies the rule group | 71 | | [firewall\_rule\_group\_stateful\_resource\_policy\_id](#output\_firewall\_rule\_group\_stateful\_resource\_policy\_id) | The Amazon Resource Name (ARN) of the rule group associated with the resource policy | 72 | | [firewall\_rule\_group\_stateful\_update\_token](#output\_firewall\_rule\_group\_stateful\_update\_token) | A string token used when updating the rule group | 73 | | [firewall\_rule\_group\_stateless\_arn](#output\_firewall\_rule\_group\_stateless\_arn) | The Amazon Resource Name (ARN) that identifies the rule group | 74 | | [firewall\_rule\_group\_stateless\_id](#output\_firewall\_rule\_group\_stateless\_id) | The Amazon Resource Name (ARN) that identifies the rule group | 75 | | [firewall\_rule\_group\_stateless\_resource\_policy\_id](#output\_firewall\_rule\_group\_stateless\_resource\_policy\_id) | The Amazon Resource Name (ARN) of the rule group associated with the resource policy | 76 | | [firewall\_rule\_group\_stateless\_update\_token](#output\_firewall\_rule\_group\_stateless\_update\_token) | A string token used when updating the rule group | 77 | | [firewall\_status](#output\_firewall\_status) | Nested list of information about the current status of the firewall | 78 | | [firewall\_update\_token](#output\_firewall\_update\_token) | A string token used when updating a firewall | 79 | 80 | 81 | Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/blob/master/LICENSE). 82 | -------------------------------------------------------------------------------- /examples/complete/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = local.region 3 | } 4 | 5 | data "aws_caller_identity" "current" {} 6 | data "aws_availability_zones" "available" {} 7 | 8 | locals { 9 | region = "us-east-1" 10 | name = "network-firewall-ex-${basename(path.cwd)}" 11 | account_id = data.aws_caller_identity.current.account_id 12 | 13 | vpc_cidr = "10.0.0.0/16" 14 | num_azs = 3 15 | azs = slice(data.aws_availability_zones.available.names, 0, local.num_azs) 16 | 17 | tags = { 18 | Name = local.name 19 | Example = local.name 20 | Repository = "https://github.com/terraform-aws-modules/terraform-aws-network-firewall" 21 | } 22 | } 23 | 24 | ################################################################################ 25 | # network firewall Module 26 | ################################################################################ 27 | 28 | module "network_firewall" { 29 | source = "../.." 30 | 31 | # Firewall 32 | name = local.name 33 | description = "Example network firewall" 34 | 35 | # Only for example 36 | delete_protection = false 37 | firewall_policy_change_protection = false 38 | subnet_change_protection = false 39 | 40 | vpc_id = module.vpc.vpc_id 41 | subnet_mapping = { for i in range(0, local.num_azs) : 42 | "subnet-${i}" => { 43 | subnet_id = element(module.vpc.public_subnets, i) 44 | ip_address_type = "IPV4" 45 | } 46 | } 47 | 48 | # Logging configuration 49 | create_logging_configuration = true 50 | logging_configuration_destination_config = [ 51 | { 52 | log_destination = { 53 | logGroup = aws_cloudwatch_log_group.logs.name 54 | } 55 | log_destination_type = "CloudWatchLogs" 56 | log_type = "ALERT" 57 | }, 58 | { 59 | log_destination = { 60 | bucketName = aws_s3_bucket.network_firewall_logs.id 61 | prefix = local.name 62 | } 63 | log_destination_type = "S3" 64 | log_type = "FLOW" 65 | } 66 | ] 67 | 68 | # Policy 69 | policy_name = local.name 70 | policy_description = "Example network firewall policy" 71 | 72 | policy_stateful_rule_group_reference = { 73 | one = { resource_arn = module.network_firewall_rule_group_stateful.arn } 74 | } 75 | 76 | policy_stateless_default_actions = ["aws:pass"] 77 | policy_stateless_fragment_default_actions = ["aws:drop"] 78 | policy_stateless_rule_group_reference = { 79 | one = { 80 | priority = 1 81 | resource_arn = module.network_firewall_rule_group_stateless.arn 82 | } 83 | } 84 | 85 | tags = local.tags 86 | } 87 | 88 | module "network_firewall_disabled" { 89 | source = "../.." 90 | 91 | create = false 92 | } 93 | 94 | ################################################################################ 95 | # Network Firewall Rule Group 96 | ################################################################################ 97 | 98 | module "network_firewall_rule_group_stateful" { 99 | source = "../../modules/rule-group" 100 | 101 | name = "${local.name}-stateful" 102 | description = "Stateful Inspection for denying access to a domain" 103 | type = "STATEFUL" 104 | capacity = 100 105 | 106 | rule_group = { 107 | rules_source = { 108 | rules_source_list = { 109 | generated_rules_type = "DENYLIST" 110 | target_types = ["HTTP_HOST"] 111 | targets = ["test.example.com"] 112 | } 113 | } 114 | } 115 | 116 | # Resource Policy 117 | create_resource_policy = true 118 | attach_resource_policy = true 119 | resource_policy_principals = ["arn:aws:iam::${local.account_id}:root"] 120 | 121 | tags = local.tags 122 | } 123 | 124 | module "network_firewall_rule_group_stateless" { 125 | source = "../../modules/rule-group" 126 | 127 | name = "${local.name}-stateless" 128 | description = "Stateless Inspection with a Custom Action" 129 | type = "STATELESS" 130 | capacity = 100 131 | 132 | rule_group = { 133 | rules_source = { 134 | stateless_rules_and_custom_actions = { 135 | custom_action = [{ 136 | action_definition = { 137 | publish_metric_action = { 138 | dimension = [{ 139 | value = "2" 140 | }] 141 | } 142 | } 143 | action_name = "ExampleMetricsAction" 144 | }] 145 | stateless_rule = [{ 146 | priority = 1 147 | rule_definition = { 148 | actions = ["aws:pass", "ExampleMetricsAction"] 149 | match_attributes = { 150 | source = [{ 151 | address_definition = "1.2.3.4/32" 152 | }] 153 | source_port = [{ 154 | from_port = 443 155 | to_port = 443 156 | }] 157 | destination = [{ 158 | address_definition = "124.1.1.5/32" 159 | }] 160 | destination_port = [{ 161 | from_port = 443 162 | to_port = 443 163 | }] 164 | protocols = [6] 165 | tcp_flag = [{ 166 | flags = ["SYN"] 167 | masks = ["SYN", "ACK"] 168 | }] 169 | } 170 | } 171 | }] 172 | } 173 | } 174 | } 175 | 176 | # Resource Policy 177 | create_resource_policy = true 178 | attach_resource_policy = true 179 | resource_policy_principals = ["arn:aws:iam::${local.account_id}:root"] 180 | 181 | tags = local.tags 182 | } 183 | 184 | ################################################################################ 185 | # Supporting Resources 186 | ################################################################################ 187 | 188 | module "vpc" { 189 | source = "terraform-aws-modules/vpc/aws" 190 | version = "~> 5.0" 191 | 192 | name = local.name 193 | cidr = local.vpc_cidr 194 | 195 | azs = local.azs 196 | public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)] 197 | private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 10)] 198 | 199 | enable_nat_gateway = true 200 | single_nat_gateway = true 201 | 202 | tags = local.tags 203 | } 204 | 205 | resource "aws_cloudwatch_log_group" "logs" { 206 | name = "${local.name}-logs" 207 | retention_in_days = 7 208 | 209 | tags = local.tags 210 | } 211 | 212 | resource "aws_s3_bucket" "network_firewall_logs" { 213 | bucket = "${local.name}-network-firewall-logs-${local.account_id}" 214 | force_destroy = true 215 | 216 | tags = local.tags 217 | } 218 | 219 | # Logging configuration automatically adds this policy if not present 220 | resource "aws_s3_bucket_policy" "network_firewall_logs" { 221 | bucket = aws_s3_bucket.network_firewall_logs.id 222 | policy = jsonencode({ 223 | Version = "2012-10-17" 224 | Statement = [ 225 | { 226 | Action = "s3:PutObject" 227 | Condition = { 228 | ArnLike = { 229 | "aws:SourceArn" = "arn:aws:logs:${local.region}:${local.account_id}:*" 230 | } 231 | StringEquals = { 232 | "aws:SourceAccount" = local.account_id 233 | "s3:x-amz-acl" = "bucket-owner-full-control" 234 | } 235 | } 236 | Effect = "Allow" 237 | Principal = { 238 | Service = "delivery.logs.amazonaws.com" 239 | } 240 | Resource = "${aws_s3_bucket.network_firewall_logs.arn}/${local.name}/AWSLogs/${local.account_id}/*" 241 | Sid = "AWSLogDeliveryWrite" 242 | }, 243 | { 244 | Action = "s3:GetBucketAcl" 245 | Condition = { 246 | ArnLike = { 247 | "aws:SourceArn" = "arn:aws:logs:${local.region}:${local.account_id}:*" 248 | } 249 | StringEquals = { 250 | "aws:SourceAccount" = local.account_id 251 | } 252 | } 253 | Effect = "Allow" 254 | Principal = { 255 | Service = "delivery.logs.amazonaws.com" 256 | } 257 | Resource = aws_s3_bucket.network_firewall_logs.arn 258 | Sid = "AWSLogDeliveryAclCheck" 259 | }, 260 | ] 261 | }) 262 | } 263 | -------------------------------------------------------------------------------- /examples/complete/outputs.tf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Firewall 3 | ################################################################################ 4 | 5 | output "firewall_id" { 6 | description = "The Amazon Resource Name (ARN) that identifies the firewall" 7 | value = module.network_firewall.id 8 | } 9 | 10 | output "firewall_arn" { 11 | description = "The Amazon Resource Name (ARN) that identifies the firewall" 12 | value = module.network_firewall.arn 13 | } 14 | 15 | output "firewall_status" { 16 | description = "Nested list of information about the current status of the firewall" 17 | value = module.network_firewall.status 18 | } 19 | 20 | output "firewall_update_token" { 21 | description = "A string token used when updating a firewall" 22 | value = module.network_firewall.update_token 23 | } 24 | 25 | ################################################################################ 26 | # Firewall Logging Configuration 27 | ################################################################################ 28 | 29 | output "firewall_logging_configuration_id" { 30 | description = "The Amazon Resource Name (ARN) of the associated firewall" 31 | value = module.network_firewall.logging_configuration_id 32 | } 33 | 34 | ################################################################################ 35 | # Firewall Policy 36 | ################################################################################ 37 | 38 | output "firewall_policy_id" { 39 | description = "The Amazon Resource Name (ARN) that identifies the firewall policy" 40 | value = module.network_firewall.policy_id 41 | } 42 | 43 | output "firewall_policy_arn" { 44 | description = "The Amazon Resource Name (ARN) that identifies the firewall policy" 45 | value = module.network_firewall.policy_arn 46 | } 47 | 48 | output "firewall_policy_update_token" { 49 | description = "A string token used when updating a firewall policy" 50 | value = module.network_firewall.policy_update_token 51 | } 52 | 53 | output "firewall_policy_resource_policy_id" { 54 | description = "The Amazon Resource Name (ARN) of the firewall policy associated with the resource policy" 55 | value = module.network_firewall.policy_resource_policy_id 56 | } 57 | 58 | ################################################################################ 59 | # Rule Group - Stateful 60 | ################################################################################ 61 | 62 | output "firewall_rule_group_stateful_id" { 63 | description = "The Amazon Resource Name (ARN) that identifies the rule group" 64 | value = module.network_firewall_rule_group_stateful.id 65 | } 66 | 67 | output "firewall_rule_group_stateful_arn" { 68 | description = "The Amazon Resource Name (ARN) that identifies the rule group" 69 | value = module.network_firewall_rule_group_stateful.arn 70 | } 71 | 72 | output "firewall_rule_group_stateful_update_token" { 73 | description = "A string token used when updating the rule group" 74 | value = module.network_firewall_rule_group_stateful.update_token 75 | } 76 | 77 | output "firewall_rule_group_stateful_resource_policy_id" { 78 | description = "The Amazon Resource Name (ARN) of the rule group associated with the resource policy" 79 | value = module.network_firewall_rule_group_stateful.resource_policy_id 80 | } 81 | 82 | ################################################################################ 83 | # Rule Group - Stateless 84 | ################################################################################ 85 | 86 | output "firewall_rule_group_stateless_id" { 87 | description = "The Amazon Resource Name (ARN) that identifies the rule group" 88 | value = module.network_firewall_rule_group_stateless.id 89 | } 90 | 91 | output "firewall_rule_group_stateless_arn" { 92 | description = "The Amazon Resource Name (ARN) that identifies the rule group" 93 | value = module.network_firewall_rule_group_stateless.arn 94 | } 95 | 96 | output "firewall_rule_group_stateless_update_token" { 97 | description = "A string token used when updating the rule group" 98 | value = module.network_firewall_rule_group_stateless.update_token 99 | } 100 | 101 | output "firewall_rule_group_stateless_resource_policy_id" { 102 | description = "The Amazon Resource Name (ARN) of the rule group associated with the resource policy" 103 | value = module.network_firewall_rule_group_stateless.resource_policy_id 104 | } 105 | -------------------------------------------------------------------------------- /examples/complete/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-network-firewall/f63f12514ad0e5f216c1690f154cff6b1c111e08/examples/complete/variables.tf -------------------------------------------------------------------------------- /examples/complete/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 5.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/separate/README.md: -------------------------------------------------------------------------------- 1 | # Separate AWS Network Firewall Example 2 | 3 | Configuration in this directory creates the following as separate module definitions: 4 | 5 | - AWS Network Firewall 6 | - AWS Network Firewall Policy 7 | - AWS Network Firewall Rule Group 8 | 9 | ## Usage 10 | 11 | To run this example you need to execute: 12 | 13 | ```bash 14 | $ terraform init 15 | $ terraform plan 16 | $ terraform apply 17 | ``` 18 | 19 | Note that this example may create resources which will incur monetary charges on your AWS bill. Run `terraform destroy` when you no longer need these resources. 20 | 21 | 22 | ## Requirements 23 | 24 | | Name | Version | 25 | |------|---------| 26 | | [terraform](#requirement\_terraform) | >= 1.0 | 27 | | [aws](#requirement\_aws) | >= 5.2 | 28 | 29 | ## Providers 30 | 31 | | Name | Version | 32 | |------|---------| 33 | | [aws](#provider\_aws) | >= 5.2 | 34 | 35 | ## Modules 36 | 37 | | Name | Source | Version | 38 | |------|--------|---------| 39 | | [network\_firewall](#module\_network\_firewall) | ../../modules/firewall | n/a | 40 | | [network\_firewall\_disabled](#module\_network\_firewall\_disabled) | ../../modules/firewall | n/a | 41 | | [network\_firewall\_policy](#module\_network\_firewall\_policy) | ../../modules/policy | n/a | 42 | | [network\_firewall\_policy\_disabled](#module\_network\_firewall\_policy\_disabled) | ../../modules/policy | n/a | 43 | | [network\_firewall\_rule\_group\_disabled](#module\_network\_firewall\_rule\_group\_disabled) | ../../modules/rule-group | n/a | 44 | | [network\_firewall\_rule\_group\_stateful](#module\_network\_firewall\_rule\_group\_stateful) | ../../modules/rule-group | n/a | 45 | | [network\_firewall\_rule\_group\_stateless](#module\_network\_firewall\_rule\_group\_stateless) | ../../modules/rule-group | n/a | 46 | | [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 5.0 | 47 | 48 | ## Resources 49 | 50 | | Name | Type | 51 | |------|------| 52 | | [aws_cloudwatch_log_group.logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | 53 | | [aws_s3_bucket.network_firewall_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket) | resource | 54 | | [aws_s3_bucket_policy.network_firewall_logs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/s3_bucket_policy) | resource | 55 | | [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | 56 | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | 57 | 58 | ## Inputs 59 | 60 | No inputs. 61 | 62 | ## Outputs 63 | 64 | | Name | Description | 65 | |------|-------------| 66 | | [firewall\_arn](#output\_firewall\_arn) | The Amazon Resource Name (ARN) that identifies the firewall | 67 | | [firewall\_id](#output\_firewall\_id) | The Amazon Resource Name (ARN) that identifies the firewall | 68 | | [firewall\_logging\_configuration\_id](#output\_firewall\_logging\_configuration\_id) | The Amazon Resource Name (ARN) of the associated firewall | 69 | | [firewall\_policy\_arn](#output\_firewall\_policy\_arn) | The Amazon Resource Name (ARN) that identifies the firewall policy | 70 | | [firewall\_policy\_id](#output\_firewall\_policy\_id) | The Amazon Resource Name (ARN) that identifies the firewall policy | 71 | | [firewall\_policy\_resource\_policy\_id](#output\_firewall\_policy\_resource\_policy\_id) | The Amazon Resource Name (ARN) of the firewall policy associated with the resource policy | 72 | | [firewall\_policy\_update\_token](#output\_firewall\_policy\_update\_token) | A string token used when updating a firewall policy | 73 | | [firewall\_rule\_group\_stateful\_arn](#output\_firewall\_rule\_group\_stateful\_arn) | The Amazon Resource Name (ARN) that identifies the rule group | 74 | | [firewall\_rule\_group\_stateful\_id](#output\_firewall\_rule\_group\_stateful\_id) | The Amazon Resource Name (ARN) that identifies the rule group | 75 | | [firewall\_rule\_group\_stateful\_resource\_policy\_id](#output\_firewall\_rule\_group\_stateful\_resource\_policy\_id) | The Amazon Resource Name (ARN) of the rule group associated with the resource policy | 76 | | [firewall\_rule\_group\_stateful\_update\_token](#output\_firewall\_rule\_group\_stateful\_update\_token) | A string token used when updating the rule group | 77 | | [firewall\_rule\_group\_stateless\_arn](#output\_firewall\_rule\_group\_stateless\_arn) | The Amazon Resource Name (ARN) that identifies the rule group | 78 | | [firewall\_rule\_group\_stateless\_id](#output\_firewall\_rule\_group\_stateless\_id) | The Amazon Resource Name (ARN) that identifies the rule group | 79 | | [firewall\_rule\_group\_stateless\_resource\_policy\_id](#output\_firewall\_rule\_group\_stateless\_resource\_policy\_id) | The Amazon Resource Name (ARN) of the rule group associated with the resource policy | 80 | | [firewall\_rule\_group\_stateless\_update\_token](#output\_firewall\_rule\_group\_stateless\_update\_token) | A string token used when updating the rule group | 81 | | [firewall\_status](#output\_firewall\_status) | Nested list of information about the current status of the firewall | 82 | | [firewall\_update\_token](#output\_firewall\_update\_token) | A string token used when updating a firewall | 83 | 84 | 85 | Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/blob/master/LICENSE). 86 | -------------------------------------------------------------------------------- /examples/separate/main.tf: -------------------------------------------------------------------------------- 1 | provider "aws" { 2 | region = local.region 3 | } 4 | 5 | data "aws_caller_identity" "current" {} 6 | data "aws_availability_zones" "available" {} 7 | 8 | locals { 9 | region = "us-east-1" 10 | name = "network-firewall-ex-${basename(path.cwd)}" 11 | account_id = data.aws_caller_identity.current.account_id 12 | 13 | vpc_cidr = "10.0.0.0/16" 14 | num_azs = 3 15 | azs = slice(data.aws_availability_zones.available.names, 0, local.num_azs) 16 | 17 | tags = { 18 | Name = local.name 19 | Example = local.name 20 | Repository = "https://github.com/terraform-aws-modules/terraform-aws-network-firewall" 21 | } 22 | } 23 | 24 | ################################################################################ 25 | # Network Firewall 26 | ################################################################################ 27 | 28 | module "network_firewall" { 29 | source = "../../modules/firewall" 30 | 31 | name = local.name 32 | description = "Example network firewall" 33 | 34 | # Only for example 35 | delete_protection = false 36 | firewall_policy_change_protection = false 37 | subnet_change_protection = false 38 | 39 | firewall_policy_arn = module.network_firewall_policy.arn 40 | 41 | vpc_id = module.vpc.vpc_id 42 | subnet_mapping = { for i in range(0, local.num_azs) : 43 | "subnet-${i}" => { 44 | subnet_id = element(module.vpc.public_subnets, i) 45 | ip_address_type = "IPV4" 46 | } 47 | } 48 | 49 | # Logging configuration 50 | create_logging_configuration = true 51 | logging_configuration_destination_config = [ 52 | { 53 | log_destination = { 54 | logGroup = aws_cloudwatch_log_group.logs.name 55 | } 56 | log_destination_type = "CloudWatchLogs" 57 | log_type = "ALERT" 58 | }, 59 | { 60 | log_destination = { 61 | bucketName = aws_s3_bucket.network_firewall_logs.id 62 | prefix = local.name 63 | } 64 | log_destination_type = "S3" 65 | log_type = "FLOW" 66 | } 67 | ] 68 | 69 | tags = local.tags 70 | } 71 | 72 | module "network_firewall_disabled" { 73 | source = "../../modules/firewall" 74 | 75 | create = false 76 | } 77 | 78 | ################################################################################ 79 | # Network Firewall Policy 80 | ################################################################################ 81 | 82 | module "network_firewall_policy" { 83 | source = "../../modules/policy" 84 | 85 | name = local.name 86 | description = "Example network firewall policy" 87 | 88 | stateful_rule_group_reference = { 89 | one = { resource_arn = module.network_firewall_rule_group_stateful.arn } 90 | } 91 | 92 | stateless_default_actions = ["aws:pass"] 93 | stateless_fragment_default_actions = ["aws:drop"] 94 | stateless_rule_group_reference = { 95 | one = { 96 | priority = 1 97 | resource_arn = module.network_firewall_rule_group_stateless.arn 98 | } 99 | } 100 | 101 | tags = local.tags 102 | } 103 | 104 | module "network_firewall_policy_disabled" { 105 | source = "../../modules/policy" 106 | 107 | create = false 108 | } 109 | 110 | ################################################################################ 111 | # Network Firewall Rule Group 112 | ################################################################################ 113 | 114 | module "network_firewall_rule_group_stateful" { 115 | source = "../../modules/rule-group" 116 | 117 | name = "${local.name}-stateful" 118 | description = "Stateful Inspection for denying access to a domain" 119 | type = "STATEFUL" 120 | capacity = 100 121 | 122 | rule_group = { 123 | rules_source = { 124 | rules_source_list = { 125 | generated_rules_type = "DENYLIST" 126 | target_types = ["HTTP_HOST"] 127 | targets = ["test.example.com"] 128 | } 129 | } 130 | } 131 | 132 | # Resource Policy 133 | create_resource_policy = true 134 | attach_resource_policy = true 135 | resource_policy_principals = ["arn:aws:iam::${local.account_id}:root"] 136 | 137 | tags = local.tags 138 | } 139 | 140 | module "network_firewall_rule_group_stateless" { 141 | source = "../../modules/rule-group" 142 | 143 | name = "${local.name}-stateless" 144 | description = "Stateless Inspection with a Custom Action" 145 | type = "STATELESS" 146 | capacity = 100 147 | 148 | rule_group = { 149 | rules_source = { 150 | stateless_rules_and_custom_actions = { 151 | custom_action = [{ 152 | action_definition = { 153 | publish_metric_action = { 154 | dimension = [{ 155 | value = "2" 156 | }] 157 | } 158 | } 159 | action_name = "ExampleMetricsAction" 160 | }] 161 | stateless_rule = [{ 162 | priority = 1 163 | rule_definition = { 164 | actions = ["aws:pass", "ExampleMetricsAction"] 165 | match_attributes = { 166 | source = [{ 167 | address_definition = "1.2.3.4/32" 168 | }] 169 | source_port = [{ 170 | from_port = 443 171 | to_port = 443 172 | }] 173 | destination = [{ 174 | address_definition = "124.1.1.5/32" 175 | }] 176 | destination_port = [{ 177 | from_port = 443 178 | to_port = 443 179 | }] 180 | protocols = [6] 181 | tcp_flag = [{ 182 | flags = ["SYN"] 183 | masks = ["SYN", "ACK"] 184 | }] 185 | } 186 | } 187 | }] 188 | } 189 | } 190 | } 191 | 192 | # Resource Policy 193 | create_resource_policy = true 194 | attach_resource_policy = true 195 | resource_policy_principals = ["arn:aws:iam::${local.account_id}:root"] 196 | 197 | tags = local.tags 198 | } 199 | 200 | module "network_firewall_rule_group_disabled" { 201 | source = "../../modules/rule-group" 202 | 203 | create = false 204 | } 205 | 206 | ################################################################################ 207 | # Supporting Resources 208 | ################################################################################ 209 | 210 | module "vpc" { 211 | source = "terraform-aws-modules/vpc/aws" 212 | version = "~> 5.0" 213 | 214 | name = local.name 215 | cidr = local.vpc_cidr 216 | 217 | azs = local.azs 218 | public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)] 219 | private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 10)] 220 | 221 | enable_nat_gateway = true 222 | single_nat_gateway = true 223 | 224 | tags = local.tags 225 | } 226 | 227 | resource "aws_cloudwatch_log_group" "logs" { 228 | name = "${local.name}-logs" 229 | retention_in_days = 7 230 | 231 | tags = local.tags 232 | } 233 | 234 | resource "aws_s3_bucket" "network_firewall_logs" { 235 | bucket = "${local.name}-network-firewall-logs-${local.account_id}" 236 | force_destroy = true 237 | 238 | tags = local.tags 239 | } 240 | 241 | # Logging configuration automatically adds this policy if not present 242 | resource "aws_s3_bucket_policy" "network_firewall_logs" { 243 | bucket = aws_s3_bucket.network_firewall_logs.id 244 | policy = jsonencode({ 245 | Version = "2012-10-17" 246 | Statement = [ 247 | { 248 | Action = "s3:PutObject" 249 | Condition = { 250 | ArnLike = { 251 | "aws:SourceArn" = "arn:aws:logs:${local.region}:${local.account_id}:*" 252 | } 253 | StringEquals = { 254 | "aws:SourceAccount" = local.account_id 255 | "s3:x-amz-acl" = "bucket-owner-full-control" 256 | } 257 | } 258 | Effect = "Allow" 259 | Principal = { 260 | Service = "delivery.logs.amazonaws.com" 261 | } 262 | Resource = "${aws_s3_bucket.network_firewall_logs.arn}/${local.name}/AWSLogs/${local.account_id}/*" 263 | Sid = "AWSLogDeliveryWrite" 264 | }, 265 | { 266 | Action = "s3:GetBucketAcl" 267 | Condition = { 268 | ArnLike = { 269 | "aws:SourceArn" = "arn:aws:logs:${local.region}:${local.account_id}:*" 270 | } 271 | StringEquals = { 272 | "aws:SourceAccount" = local.account_id 273 | } 274 | } 275 | Effect = "Allow" 276 | Principal = { 277 | Service = "delivery.logs.amazonaws.com" 278 | } 279 | Resource = aws_s3_bucket.network_firewall_logs.arn 280 | Sid = "AWSLogDeliveryAclCheck" 281 | }, 282 | ] 283 | }) 284 | } 285 | -------------------------------------------------------------------------------- /examples/separate/outputs.tf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Firewall 3 | ################################################################################ 4 | 5 | output "firewall_id" { 6 | description = "The Amazon Resource Name (ARN) that identifies the firewall" 7 | value = module.network_firewall.id 8 | } 9 | 10 | output "firewall_arn" { 11 | description = "The Amazon Resource Name (ARN) that identifies the firewall" 12 | value = module.network_firewall.arn 13 | } 14 | 15 | output "firewall_status" { 16 | description = "Nested list of information about the current status of the firewall" 17 | value = module.network_firewall.status 18 | } 19 | 20 | output "firewall_update_token" { 21 | description = "A string token used when updating a firewall" 22 | value = module.network_firewall.update_token 23 | } 24 | 25 | ################################################################################ 26 | # Firewall Logging Configuration 27 | ################################################################################ 28 | 29 | output "firewall_logging_configuration_id" { 30 | description = "The Amazon Resource Name (ARN) of the associated firewall" 31 | value = module.network_firewall.logging_configuration_id 32 | } 33 | 34 | ################################################################################ 35 | # Firewall Policy 36 | ################################################################################ 37 | 38 | output "firewall_policy_id" { 39 | description = "The Amazon Resource Name (ARN) that identifies the firewall policy" 40 | value = module.network_firewall_policy.id 41 | } 42 | 43 | output "firewall_policy_arn" { 44 | description = "The Amazon Resource Name (ARN) that identifies the firewall policy" 45 | value = module.network_firewall_policy.arn 46 | } 47 | 48 | output "firewall_policy_update_token" { 49 | description = "A string token used when updating a firewall policy" 50 | value = module.network_firewall_policy.update_token 51 | } 52 | 53 | output "firewall_policy_resource_policy_id" { 54 | description = "The Amazon Resource Name (ARN) of the firewall policy associated with the resource policy" 55 | value = module.network_firewall_policy.resource_policy_id 56 | } 57 | 58 | ################################################################################ 59 | # Rule Group - Stateful 60 | ################################################################################ 61 | 62 | output "firewall_rule_group_stateful_id" { 63 | description = "The Amazon Resource Name (ARN) that identifies the rule group" 64 | value = module.network_firewall_rule_group_stateful.id 65 | } 66 | 67 | output "firewall_rule_group_stateful_arn" { 68 | description = "The Amazon Resource Name (ARN) that identifies the rule group" 69 | value = module.network_firewall_rule_group_stateful.arn 70 | } 71 | 72 | output "firewall_rule_group_stateful_update_token" { 73 | description = "A string token used when updating the rule group" 74 | value = module.network_firewall_rule_group_stateful.update_token 75 | } 76 | 77 | output "firewall_rule_group_stateful_resource_policy_id" { 78 | description = "The Amazon Resource Name (ARN) of the rule group associated with the resource policy" 79 | value = module.network_firewall_rule_group_stateful.resource_policy_id 80 | } 81 | 82 | ################################################################################ 83 | # Rule Group - Stateless 84 | ################################################################################ 85 | 86 | output "firewall_rule_group_stateless_id" { 87 | description = "The Amazon Resource Name (ARN) that identifies the rule group" 88 | value = module.network_firewall_rule_group_stateless.id 89 | } 90 | 91 | output "firewall_rule_group_stateless_arn" { 92 | description = "The Amazon Resource Name (ARN) that identifies the rule group" 93 | value = module.network_firewall_rule_group_stateless.arn 94 | } 95 | 96 | output "firewall_rule_group_stateless_update_token" { 97 | description = "A string token used when updating the rule group" 98 | value = module.network_firewall_rule_group_stateless.update_token 99 | } 100 | 101 | output "firewall_rule_group_stateless_resource_policy_id" { 102 | description = "The Amazon Resource Name (ARN) of the rule group associated with the resource policy" 103 | value = module.network_firewall_rule_group_stateless.resource_policy_id 104 | } 105 | -------------------------------------------------------------------------------- /examples/separate/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/terraform-aws-modules/terraform-aws-network-firewall/f63f12514ad0e5f216c1690f154cff6b1c111e08/examples/separate/variables.tf -------------------------------------------------------------------------------- /examples/separate/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 5.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Network Firewall 3 | ################################################################################ 4 | 5 | module "firewall" { 6 | source = "./modules/firewall" 7 | 8 | create = var.create 9 | 10 | # Firewall 11 | delete_protection = var.delete_protection 12 | description = var.description 13 | encryption_configuration = var.encryption_configuration 14 | firewall_policy_arn = var.create_policy ? module.policy.arn : var.firewall_policy_arn 15 | firewall_policy_change_protection = var.firewall_policy_change_protection 16 | name = var.name 17 | subnet_change_protection = var.subnet_change_protection 18 | subnet_mapping = var.subnet_mapping 19 | vpc_id = var.vpc_id 20 | 21 | # Logging 22 | create_logging_configuration = var.create_logging_configuration 23 | logging_configuration_destination_config = var.logging_configuration_destination_config 24 | 25 | tags = var.tags 26 | } 27 | 28 | ################################################################################ 29 | # Policy 30 | ################################################################################ 31 | 32 | module "policy" { 33 | source = "./modules/policy" 34 | 35 | create = var.create && var.create_policy 36 | 37 | # Policy 38 | description = var.policy_description 39 | encryption_configuration = var.policy_encryption_configuration 40 | stateful_default_actions = var.policy_stateful_default_actions 41 | stateful_engine_options = var.policy_stateful_engine_options 42 | stateful_rule_group_reference = var.policy_stateful_rule_group_reference 43 | stateless_custom_action = var.policy_stateless_custom_action 44 | stateless_default_actions = var.policy_stateless_default_actions 45 | stateless_fragment_default_actions = var.policy_stateless_fragment_default_actions 46 | stateless_rule_group_reference = var.policy_stateless_rule_group_reference 47 | name = try(coalesce(var.policy_name, var.name), "") 48 | 49 | # Resource policy 50 | create_resource_policy = var.create_policy_resource_policy 51 | resource_policy_actions = var.policy_resource_policy_actions 52 | resource_policy_principals = var.policy_resource_policy_principals 53 | attach_resource_policy = var.policy_attach_resource_policy 54 | resource_policy = var.policy_resource_policy 55 | 56 | # RAM resource association 57 | ram_resource_associations = var.policy_ram_resource_associations 58 | 59 | tags = merge(var.tags, var.policy_tags) 60 | } 61 | -------------------------------------------------------------------------------- /modules/firewall/README.md: -------------------------------------------------------------------------------- 1 | # AWS Network Firewall Terraform Module 2 | 3 | Terraform module which creates AWS Network Firewall resources. 4 | 5 | ## Usage 6 | 7 | See [`examples`](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/tree/master/examples) directory for working examples to reference: 8 | 9 | ```hcl 10 | module "network_firewall" { 11 | source = "terraform-aws-modules/network-firewall/aws//modules/firewall" 12 | 13 | # Firewall 14 | name = "exampple" 15 | description = "Example network firewall" 16 | 17 | vpc_id = "vpc-1234556abcdef" 18 | subnet_mapping = { 19 | subnet1 = { 20 | subnet_id = "subnet-abcde012" 21 | ip_address_type = "IPV4" 22 | } 23 | subnet2 = { 24 | subnet_id = "subnet-bcde012a" 25 | ip_address_type = "IPV4" 26 | } 27 | subnet2 = { 28 | subnet_id = "subnet-fghi345a" 29 | ip_address_type = "IPV4" 30 | } 31 | } 32 | 33 | # Logging configuration 34 | create_logging_configuration = true 35 | logging_configuration_destination_config = [ 36 | { 37 | log_destination = { 38 | logGroup = "/aws/network-firewall/example" 39 | } 40 | log_destination_type = "CloudWatchLogs" 41 | log_type = "ALERT" 42 | }, 43 | { 44 | log_destination = { 45 | bucketName = "s3-example-bucket-firewall-flow-logs" 46 | prefix = "example" 47 | } 48 | log_destination_type = "S3" 49 | log_type = "FLOW" 50 | } 51 | ] 52 | 53 | tags = { 54 | Terraform = "true" 55 | Environment = "dev" 56 | } 57 | } 58 | ``` 59 | 60 | 61 | ## Requirements 62 | 63 | | Name | Version | 64 | |------|---------| 65 | | [terraform](#requirement\_terraform) | >= 1.0 | 66 | | [aws](#requirement\_aws) | >= 5.2 | 67 | 68 | ## Providers 69 | 70 | | Name | Version | 71 | |------|---------| 72 | | [aws](#provider\_aws) | >= 5.2 | 73 | 74 | ## Modules 75 | 76 | No modules. 77 | 78 | ## Resources 79 | 80 | | Name | Type | 81 | |------|------| 82 | | [aws_networkfirewall_firewall.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall) | resource | 83 | | [aws_networkfirewall_logging_configuration.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_logging_configuration) | resource | 84 | 85 | ## Inputs 86 | 87 | | Name | Description | Type | Default | Required | 88 | |------|-------------|------|---------|:--------:| 89 | | [create](#input\_create) | Controls if resources should be created | `bool` | `true` | no | 90 | | [create\_logging\_configuration](#input\_create\_logging\_configuration) | Controls if a Logging Configuration should be created | `bool` | `false` | no | 91 | | [delete\_protection](#input\_delete\_protection) | A boolean flag indicating whether it is possible to delete the firewall. Defaults to `true` | `bool` | `true` | no | 92 | | [description](#input\_description) | A friendly description of the firewall | `string` | `""` | no | 93 | | [encryption\_configuration](#input\_encryption\_configuration) | KMS encryption configuration settings | `any` | `{}` | no | 94 | | [firewall\_policy\_arn](#input\_firewall\_policy\_arn) | The ARN of the Firewall Policy to use | `string` | `""` | no | 95 | | [firewall\_policy\_change\_protection](#input\_firewall\_policy\_change\_protection) | A boolean flag indicating whether it is possible to change the associated firewall policy. Defaults to `false` | `bool` | `null` | no | 96 | | [logging\_configuration\_destination\_config](#input\_logging\_configuration\_destination\_config) | A list of min 1, max 2 configuration blocks describing the destination for the logging configuration | `any` | `[]` | no | 97 | | [name](#input\_name) | A friendly name of the firewall | `string` | `""` | no | 98 | | [subnet\_change\_protection](#input\_subnet\_change\_protection) | A boolean flag indicating whether it is possible to change the associated subnet(s). Defaults to `true` | `bool` | `true` | no | 99 | | [subnet\_mapping](#input\_subnet\_mapping) | Set of configuration blocks describing the public subnets. Each subnet must belong to a different Availability Zone in the VPC. AWS Network Firewall creates a firewall endpoint in each subnet | `any` | `{}` | no | 100 | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | 101 | | [vpc\_id](#input\_vpc\_id) | The unique identifier of the VPC where AWS Network Firewall should create the firewall | `string` | `""` | no | 102 | 103 | ## Outputs 104 | 105 | | Name | Description | 106 | |------|-------------| 107 | | [arn](#output\_arn) | The Amazon Resource Name (ARN) that identifies the firewall | 108 | | [id](#output\_id) | The Amazon Resource Name (ARN) that identifies the firewall | 109 | | [logging\_configuration\_id](#output\_logging\_configuration\_id) | The Amazon Resource Name (ARN) of the associated firewall | 110 | | [status](#output\_status) | Nested list of information about the current status of the firewall | 111 | | [update\_token](#output\_update\_token) | A string token used when updating a firewall | 112 | 113 | 114 | ## License 115 | 116 | Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/blob/master/LICENSE). 117 | -------------------------------------------------------------------------------- /modules/firewall/main.tf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Firewall 3 | ################################################################################ 4 | 5 | resource "aws_networkfirewall_firewall" "this" { 6 | count = var.create ? 1 : 0 7 | 8 | delete_protection = var.delete_protection 9 | description = var.description 10 | 11 | dynamic "encryption_configuration" { 12 | for_each = length(var.encryption_configuration) > 0 ? [var.encryption_configuration] : [] 13 | 14 | content { 15 | key_id = try(encryption_configuration.value.key_id, null) 16 | type = encryption_configuration.value.type 17 | } 18 | } 19 | 20 | firewall_policy_arn = var.firewall_policy_arn 21 | firewall_policy_change_protection = var.firewall_policy_change_protection 22 | name = var.name 23 | subnet_change_protection = var.subnet_change_protection 24 | 25 | dynamic "subnet_mapping" { 26 | for_each = var.subnet_mapping 27 | 28 | content { 29 | ip_address_type = try(subnet_mapping.value.ip_address_type, null) 30 | subnet_id = subnet_mapping.value.subnet_id 31 | } 32 | } 33 | 34 | vpc_id = var.vpc_id 35 | 36 | tags = var.tags 37 | } 38 | 39 | ################################################################################ 40 | # Logging Configuration 41 | ################################################################################ 42 | 43 | resource "aws_networkfirewall_logging_configuration" "this" { 44 | count = var.create && var.create_logging_configuration ? 1 : 0 45 | 46 | firewall_arn = aws_networkfirewall_firewall.this[0].arn 47 | 48 | logging_configuration { 49 | # At least one config, at most, only two blocks can be specified; one for `FLOW` logs and one for `ALERT` logs. 50 | dynamic "log_destination_config" { 51 | for_each = var.logging_configuration_destination_config 52 | content { 53 | log_destination = log_destination_config.value.log_destination 54 | log_destination_type = log_destination_config.value.log_destination_type 55 | log_type = log_destination_config.value.log_type 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /modules/firewall/outputs.tf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Firewall 3 | ################################################################################ 4 | 5 | output "id" { 6 | description = "The Amazon Resource Name (ARN) that identifies the firewall" 7 | value = try(aws_networkfirewall_firewall.this[0].id, null) 8 | } 9 | 10 | output "arn" { 11 | description = "The Amazon Resource Name (ARN) that identifies the firewall" 12 | value = try(aws_networkfirewall_firewall.this[0].arn, null) 13 | } 14 | 15 | output "status" { 16 | description = "Nested list of information about the current status of the firewall" 17 | value = try(aws_networkfirewall_firewall.this[0].firewall_status, null) 18 | } 19 | 20 | output "update_token" { 21 | description = "A string token used when updating a firewall" 22 | value = try(aws_networkfirewall_firewall.this[0].update_token, null) 23 | } 24 | 25 | ################################################################################ 26 | # Firewall Logging Configuration 27 | ################################################################################ 28 | 29 | output "logging_configuration_id" { 30 | description = "The Amazon Resource Name (ARN) of the associated firewall" 31 | value = try(aws_networkfirewall_logging_configuration.this[0].id, null) 32 | } 33 | -------------------------------------------------------------------------------- /modules/firewall/variables.tf: -------------------------------------------------------------------------------- 1 | variable "create" { 2 | description = "Controls if resources should be created" 3 | type = bool 4 | default = true 5 | } 6 | 7 | variable "tags" { 8 | description = "A map of tags to add to all resources" 9 | type = map(string) 10 | default = {} 11 | } 12 | 13 | ################################################################################ 14 | # Firewall 15 | ################################################################################ 16 | 17 | variable "delete_protection" { 18 | description = "A boolean flag indicating whether it is possible to delete the firewall. Defaults to `true`" 19 | type = bool 20 | default = true 21 | } 22 | 23 | variable "description" { 24 | description = "A friendly description of the firewall" 25 | type = string 26 | default = "" 27 | } 28 | 29 | variable "encryption_configuration" { 30 | description = "KMS encryption configuration settings" 31 | type = any 32 | default = {} 33 | } 34 | 35 | variable "firewall_policy_arn" { 36 | description = "The ARN of the Firewall Policy to use" 37 | type = string 38 | default = "" 39 | } 40 | 41 | variable "firewall_policy_change_protection" { 42 | description = "A boolean flag indicating whether it is possible to change the associated firewall policy. Defaults to `false`" 43 | type = bool 44 | default = null 45 | } 46 | 47 | variable "name" { 48 | description = "A friendly name of the firewall" 49 | type = string 50 | default = "" 51 | } 52 | 53 | variable "subnet_change_protection" { 54 | description = "A boolean flag indicating whether it is possible to change the associated subnet(s). Defaults to `true`" 55 | type = bool 56 | default = true 57 | } 58 | 59 | variable "subnet_mapping" { 60 | description = "Set of configuration blocks describing the public subnets. Each subnet must belong to a different Availability Zone in the VPC. AWS Network Firewall creates a firewall endpoint in each subnet" 61 | type = any 62 | default = {} 63 | } 64 | 65 | variable "vpc_id" { 66 | description = "The unique identifier of the VPC where AWS Network Firewall should create the firewall" 67 | type = string 68 | default = "" 69 | } 70 | 71 | ################################################################################ 72 | # Firewall Logging Configuration 73 | ################################################################################ 74 | 75 | variable "create_logging_configuration" { 76 | description = "Controls if a Logging Configuration should be created" 77 | type = bool 78 | default = false 79 | } 80 | 81 | variable "logging_configuration_destination_config" { 82 | description = "A list of min 1, max 2 configuration blocks describing the destination for the logging configuration" 83 | type = any 84 | default = [] 85 | } 86 | -------------------------------------------------------------------------------- /modules/firewall/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 5.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /modules/policy/README.md: -------------------------------------------------------------------------------- 1 | # AWS Network Firewall Policy Terraform Module 2 | 3 | Terraform module which creates AWS Network Firewall policy resources. 4 | 5 | ## Usage 6 | 7 | See [`examples`](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/tree/master/examples) directory for working examples to reference: 8 | 9 | ```hcl 10 | module "network_firewall_policy" { 11 | source = "terraform-aws-modules/network-firewall/aws//modules/policy" 12 | 13 | name = "example" 14 | description = "Example network firewall policy" 15 | 16 | stateful_rule_group_reference = { 17 | one = { 18 | priority = 0 19 | resource_arn = "arn:aws:network-firewall:us-east-1:1234567890:stateful-rulegroup/example" 20 | } 21 | } 22 | 23 | stateless_default_actions = ["aws:pass"] 24 | stateless_fragment_default_actions = ["aws:drop"] 25 | stateless_rule_group_reference = { 26 | one = { 27 | priority = 0 28 | resource_arn = "arn:aws:network-firewall:us-east-1:1234567890:stateless-rulegroup/example" 29 | } 30 | } 31 | 32 | tags = { 33 | Terraform = "true" 34 | Environment = "dev" 35 | } 36 | } 37 | ``` 38 | 39 | 40 | ## Requirements 41 | 42 | | Name | Version | 43 | |------|---------| 44 | | [terraform](#requirement\_terraform) | >= 1.0 | 45 | | [aws](#requirement\_aws) | >= 5.2 | 46 | 47 | ## Providers 48 | 49 | | Name | Version | 50 | |------|---------| 51 | | [aws](#provider\_aws) | >= 5.2 | 52 | 53 | ## Modules 54 | 55 | No modules. 56 | 57 | ## Resources 58 | 59 | | Name | Type | 60 | |------|------| 61 | | [aws_networkfirewall_firewall_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy) | resource | 62 | | [aws_networkfirewall_resource_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_resource_policy) | resource | 63 | | [aws_ram_resource_association.firewall_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_association) | resource | 64 | | [aws_iam_policy_document.firewall_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 65 | 66 | ## Inputs 67 | 68 | | Name | Description | Type | Default | Required | 69 | |------|-------------|------|---------|:--------:| 70 | | [attach\_resource\_policy](#input\_attach\_resource\_policy) | Controls if a resource policy should be attached to the firewall policy | `bool` | `false` | no | 71 | | [create](#input\_create) | Controls if resources should be created | `bool` | `true` | no | 72 | | [create\_resource\_policy](#input\_create\_resource\_policy) | Controls if a resource policy should be created | `bool` | `false` | no | 73 | | [description](#input\_description) | A friendly description of the firewall policy | `string` | `null` | no | 74 | | [encryption\_configuration](#input\_encryption\_configuration) | KMS encryption configuration settings | `any` | `{}` | no | 75 | | [name](#input\_name) | A friendly name of the firewall policy | `string` | `""` | no | 76 | | [ram\_resource\_associations](#input\_ram\_resource\_associations) | A map of RAM resource associations for the created firewall policy | `map(string)` | `{}` | no | 77 | | [resource\_policy](#input\_resource\_policy) | The policy JSON to use for the resource policy; required when `create_resource_policy` is `false` | `string` | `""` | no | 78 | | [resource\_policy\_actions](#input\_resource\_policy\_actions) | A list of IAM actions allowed in the resource policy | `list(string)` | `[]` | no | 79 | | [resource\_policy\_principals](#input\_resource\_policy\_principals) | A list of IAM principals allowed in the resource policy | `list(string)` | `[]` | no | 80 | | [stateful\_default\_actions](#input\_stateful\_default\_actions) | Set of actions to take on a packet if it does not match any stateful rules in the policy. This can only be specified if the policy has a `stateful_engine_options` block with a rule\_order value of `STRICT_ORDER`. You can specify one of either or neither values of `aws:drop_strict` or `aws:drop_established`, as well as any combination of `aws:alert_strict` and `aws:alert_established` | `list(string)` | `[]` | no | 81 | | [stateful\_engine\_options](#input\_stateful\_engine\_options) | A configuration block that defines options on how the policy handles stateful rules. See [Stateful Engine Options](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy#stateful-engine-options) for details | `any` | `{}` | no | 82 | | [stateful\_rule\_group\_reference](#input\_stateful\_rule\_group\_reference) | Set of configuration blocks containing references to the stateful rule groups that are used in the policy. See [Stateful Rule Group Reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy#stateful-rule-group-reference) for details | `any` | `{}` | no | 83 | | [stateless\_custom\_action](#input\_stateless\_custom\_action) | Set of configuration blocks describing the custom action definitions that are available for use in the firewall policy's `stateless_default_actions` | `any` | `{}` | no | 84 | | [stateless\_default\_actions](#input\_stateless\_default\_actions) | Set of actions to take on a packet if it does not match any of the stateless rules in the policy. You must specify one of the standard actions including: `aws:drop`, `aws:pass`, or `aws:forward_to_sfe` | `list(string)` |
"aws:pass"
]
[| no | 85 | | [stateless\_fragment\_default\_actions](#input\_stateless\_fragment\_default\_actions) | Set of actions to take on a fragmented packet if it does not match any of the stateless rules in the policy. You must specify one of the standard actions including: `aws:drop`, `aws:pass`, or `aws:forward_to_sfe` | `list(string)` |
"aws:pass"
]
[| no | 86 | | [stateless\_rule\_group\_reference](#input\_stateless\_rule\_group\_reference) | Set of configuration blocks containing references to the stateless rule groups that are used in the policy. See [Stateless Rule Group Reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy#stateless-rule-group-reference) for details | `any` | `{}` | no | 87 | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | 88 | 89 | ## Outputs 90 | 91 | | Name | Description | 92 | |------|-------------| 93 | | [arn](#output\_arn) | The Amazon Resource Name (ARN) that identifies the firewall policy | 94 | | [id](#output\_id) | The Amazon Resource Name (ARN) that identifies the firewall policy | 95 | | [resource\_policy\_id](#output\_resource\_policy\_id) | The Amazon Resource Name (ARN) of the firewall policy associated with the resource policy | 96 | | [update\_token](#output\_update\_token) | A string token used when updating a firewall policy | 97 | 98 | 99 | ## License 100 | 101 | Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/blob/master/LICENSE). 102 | -------------------------------------------------------------------------------- /modules/policy/main.tf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Firewall Policy 3 | ################################################################################ 4 | 5 | resource "aws_networkfirewall_firewall_policy" "this" { 6 | count = var.create ? 1 : 0 7 | 8 | description = var.description 9 | 10 | dynamic "encryption_configuration" { 11 | for_each = length(var.encryption_configuration) > 0 ? [var.encryption_configuration] : [] 12 | 13 | content { 14 | key_id = try(encryption_configuration.value.key_id, null) 15 | type = encryption_configuration.value.type 16 | } 17 | } 18 | 19 | firewall_policy { 20 | # Stateful 21 | stateful_default_actions = var.stateful_default_actions 22 | 23 | dynamic "stateful_engine_options" { 24 | for_each = length(var.stateful_engine_options) > 0 ? [var.stateful_engine_options] : [] 25 | 26 | content { 27 | rule_order = try(stateful_engine_options.value.rule_order, null) 28 | stream_exception_policy = try(stateful_engine_options.value.stream_exception_policy, null) 29 | } 30 | } 31 | 32 | dynamic "stateful_rule_group_reference" { 33 | for_each = var.stateful_rule_group_reference 34 | 35 | content { 36 | dynamic "override" { 37 | for_each = try([stateful_rule_group_reference.value.override], []) 38 | 39 | content { 40 | action = try(override.value.action, null) 41 | } 42 | } 43 | 44 | priority = try(stateful_rule_group_reference.value.priority, null) 45 | resource_arn = stateful_rule_group_reference.value.resource_arn 46 | } 47 | } 48 | 49 | # Stateless 50 | dynamic "stateless_custom_action" { 51 | for_each = var.stateless_custom_action 52 | 53 | content { 54 | action_name = stateless_custom_action.value.action_name 55 | 56 | dynamic "action_definition" { 57 | for_each = stateless_custom_action.value.action_definition 58 | 59 | content { 60 | dynamic "publish_metric_action" { 61 | for_each = action_definition.value.publish_metric_action 62 | 63 | content { 64 | dynamic "dimension" { 65 | for_each = publish_metric_action.value.dimension 66 | 67 | content { 68 | value = dimension.value.value 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | } 76 | } 77 | 78 | stateless_default_actions = var.stateless_default_actions 79 | stateless_fragment_default_actions = var.stateless_fragment_default_actions 80 | 81 | dynamic "stateless_rule_group_reference" { 82 | for_each = var.stateless_rule_group_reference 83 | 84 | content { 85 | priority = stateless_rule_group_reference.value.priority 86 | resource_arn = stateless_rule_group_reference.value.resource_arn 87 | } 88 | } 89 | } 90 | 91 | name = var.name 92 | 93 | tags = var.tags 94 | } 95 | 96 | ################################################################################ 97 | # Resource Policy 98 | ################################################################################ 99 | 100 | data "aws_iam_policy_document" "firewall_policy" { 101 | count = var.create && var.create_resource_policy ? 1 : 0 102 | 103 | statement { 104 | sid = "NetworkFirewallResourcePolicy" 105 | actions = distinct(concat( 106 | var.resource_policy_actions, 107 | # policy must include the following operations 108 | [ 109 | "network-firewall:ListFirewallPolicies", 110 | "network-firewall:CreateFirewall", 111 | "network-firewall:UpdateFirewall", 112 | "network-firewall:AssociateFirewallPolicy", 113 | ] 114 | )) 115 | resources = [aws_networkfirewall_firewall_policy.this[0].arn] 116 | 117 | principals { 118 | type = "AWS" 119 | identifiers = var.resource_policy_principals 120 | } 121 | } 122 | } 123 | 124 | resource "aws_networkfirewall_resource_policy" "this" { 125 | count = var.create && var.attach_resource_policy ? 1 : 0 126 | 127 | resource_arn = aws_networkfirewall_firewall_policy.this[0].arn 128 | policy = var.create_resource_policy ? data.aws_iam_policy_document.firewall_policy[0].json : var.resource_policy 129 | } 130 | 131 | ################################################################################ 132 | # RAM Resource Association 133 | ################################################################################ 134 | 135 | resource "aws_ram_resource_association" "firewall_policy" { 136 | for_each = { for k, v in var.ram_resource_associations : k => v if var.create } 137 | 138 | resource_arn = aws_networkfirewall_firewall_policy.this[0].arn 139 | resource_share_arn = each.value.resource_share_arn 140 | } 141 | -------------------------------------------------------------------------------- /modules/policy/outputs.tf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Firewall Policy 3 | ################################################################################ 4 | 5 | output "id" { 6 | description = "The Amazon Resource Name (ARN) that identifies the firewall policy" 7 | value = try(aws_networkfirewall_firewall_policy.this[0].id, null) 8 | } 9 | 10 | output "arn" { 11 | description = "The Amazon Resource Name (ARN) that identifies the firewall policy" 12 | value = try(aws_networkfirewall_firewall_policy.this[0].arn, null) 13 | } 14 | 15 | output "update_token" { 16 | description = "A string token used when updating a firewall policy" 17 | value = try(aws_networkfirewall_firewall_policy.this[0].update_token, null) 18 | } 19 | 20 | ################################################################################ 21 | # Resource Policy 22 | ################################################################################ 23 | 24 | output "resource_policy_id" { 25 | description = "The Amazon Resource Name (ARN) of the firewall policy associated with the resource policy" 26 | value = try(aws_networkfirewall_resource_policy.this[0].id, null) 27 | } 28 | -------------------------------------------------------------------------------- /modules/policy/variables.tf: -------------------------------------------------------------------------------- 1 | variable "create" { 2 | description = "Controls if resources should be created" 3 | type = bool 4 | default = true 5 | } 6 | 7 | variable "tags" { 8 | description = "A map of tags to add to all resources" 9 | type = map(string) 10 | default = {} 11 | } 12 | 13 | ################################################################################ 14 | # Firewall Policy 15 | ################################################################################ 16 | 17 | variable "description" { 18 | description = "A friendly description of the firewall policy" 19 | type = string 20 | default = null 21 | } 22 | 23 | variable "encryption_configuration" { 24 | description = "KMS encryption configuration settings" 25 | type = any 26 | default = {} 27 | } 28 | 29 | variable "stateful_default_actions" { 30 | description = "Set of actions to take on a packet if it does not match any stateful rules in the policy. This can only be specified if the policy has a `stateful_engine_options` block with a rule_order value of `STRICT_ORDER`. You can specify one of either or neither values of `aws:drop_strict` or `aws:drop_established`, as well as any combination of `aws:alert_strict` and `aws:alert_established`" 31 | type = list(string) 32 | default = [] 33 | } 34 | 35 | variable "stateful_engine_options" { 36 | description = "A configuration block that defines options on how the policy handles stateful rules. See [Stateful Engine Options](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy#stateful-engine-options) for details" 37 | type = any 38 | default = {} 39 | } 40 | 41 | variable "stateful_rule_group_reference" { 42 | description = "Set of configuration blocks containing references to the stateful rule groups that are used in the policy. See [Stateful Rule Group Reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy#stateful-rule-group-reference) for details" 43 | type = any 44 | default = {} 45 | } 46 | 47 | variable "stateless_custom_action" { 48 | description = "Set of configuration blocks describing the custom action definitions that are available for use in the firewall policy's `stateless_default_actions`" 49 | type = any 50 | default = {} 51 | } 52 | 53 | variable "stateless_default_actions" { 54 | description = "Set of actions to take on a packet if it does not match any of the stateless rules in the policy. You must specify one of the standard actions including: `aws:drop`, `aws:pass`, or `aws:forward_to_sfe`" 55 | type = list(string) 56 | default = ["aws:pass"] 57 | } 58 | 59 | variable "stateless_fragment_default_actions" { 60 | description = "Set of actions to take on a fragmented packet if it does not match any of the stateless rules in the policy. You must specify one of the standard actions including: `aws:drop`, `aws:pass`, or `aws:forward_to_sfe`" 61 | type = list(string) 62 | default = ["aws:pass"] 63 | } 64 | 65 | variable "stateless_rule_group_reference" { 66 | description = "Set of configuration blocks containing references to the stateless rule groups that are used in the policy. See [Stateless Rule Group Reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy#stateless-rule-group-reference) for details" 67 | type = any 68 | default = {} 69 | } 70 | 71 | variable "name" { 72 | description = "A friendly name of the firewall policy" 73 | type = string 74 | default = "" 75 | } 76 | 77 | ################################################################################ 78 | # Resource Policies 79 | ################################################################################ 80 | 81 | variable "create_resource_policy" { 82 | description = "Controls if a resource policy should be created" 83 | type = bool 84 | default = false 85 | } 86 | 87 | variable "resource_policy_actions" { 88 | description = "A list of IAM actions allowed in the resource policy" 89 | type = list(string) 90 | default = [] 91 | } 92 | 93 | variable "resource_policy_principals" { 94 | description = "A list of IAM principals allowed in the resource policy" 95 | type = list(string) 96 | default = [] 97 | } 98 | 99 | variable "attach_resource_policy" { 100 | description = "Controls if a resource policy should be attached to the firewall policy" 101 | type = bool 102 | default = false 103 | } 104 | 105 | variable "resource_policy" { 106 | description = "The policy JSON to use for the resource policy; required when `create_resource_policy` is `false`" 107 | type = string 108 | default = "" 109 | } 110 | 111 | ################################################################################ 112 | # RAM Resource Association 113 | ################################################################################ 114 | 115 | variable "ram_resource_associations" { 116 | description = "A map of RAM resource associations for the created firewall policy" 117 | type = map(string) 118 | default = {} 119 | } 120 | -------------------------------------------------------------------------------- /modules/policy/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 5.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /modules/rule-group/README.md: -------------------------------------------------------------------------------- 1 | # AWS Network Firewall Rule Group Terraform Module 2 | 3 | Terraform module which creates AWS Network Firewall rule group resources. 4 | 5 | ## Usage 6 | 7 | See [`examples`](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/tree/master/examples) directory for working examples to reference: 8 | 9 | ### Stateful 10 | 11 | ```hcl 12 | module "network_firewall_rule_group_stateful" { 13 | source = "terraform-aws-modules/network-firewall/aws//modules/rule-group" 14 | 15 | name = "example-stateful" 16 | description = "Stateful Inspection for denying access to a domain" 17 | type = "STATEFUL" 18 | capacity = 100 19 | 20 | rule_group = { 21 | rules_source = { 22 | rules_source_list = { 23 | generated_rules_type = "DENYLIST" 24 | target_types = ["HTTP_HOST"] 25 | targets = ["test.example.com"] 26 | } 27 | } 28 | } 29 | 30 | # Resource Policy 31 | create_resource_policy = true 32 | attach_resource_policy = true 33 | resource_policy_principals = ["arn:aws:iam::1234567890:root"] 34 | 35 | tags = { 36 | Terraform = "true" 37 | Environment = "dev" 38 | } 39 | } 40 | ``` 41 | 42 | ### Stateless 43 | 44 | ```hcl 45 | module "network_firewall_rule_group_stateless" { 46 | source = "terraform-aws-modules/network-firewall/aws//modules/rule-group" 47 | 48 | name = "example-stateless" 49 | description = "Stateless Inspection with a Custom Action" 50 | type = "STATELESS" 51 | capacity = 100 52 | 53 | rule_group = { 54 | rules_source = { 55 | stateless_rules_and_custom_actions = { 56 | custom_action = [{ 57 | action_definition = { 58 | publish_metric_action = { 59 | dimension = [{ 60 | value = "2" 61 | }] 62 | } 63 | } 64 | action_name = "ExampleMetricsAction" 65 | }] 66 | stateless_rule = [{ 67 | priority = 1 68 | rule_definition = { 69 | actions = ["aws:pass", "ExampleMetricsAction"] 70 | match_attributes = { 71 | source = [{ 72 | address_definition = "1.2.3.4/32" 73 | }] 74 | source_port = [{ 75 | from_port = 443 76 | to_port = 443 77 | }] 78 | destination = [{ 79 | address_definition = "124.1.1.5/32" 80 | }] 81 | destination_port = [{ 82 | from_port = 443 83 | to_port = 443 84 | }] 85 | protocols = [6] 86 | tcp_flag = [{ 87 | flags = ["SYN"] 88 | masks = ["SYN", "ACK"] 89 | }] 90 | } 91 | } 92 | }] 93 | } 94 | } 95 | } 96 | 97 | # Resource Policy 98 | create_resource_policy = true 99 | attach_resource_policy = true 100 | resource_policy_principals = ["arn:aws:iam::1234567890:root"] 101 | 102 | tags = { 103 | Terraform = "true" 104 | Environment = "dev" 105 | } 106 | } 107 | ``` 108 | 109 | 110 | ## Requirements 111 | 112 | | Name | Version | 113 | |------|---------| 114 | | [terraform](#requirement\_terraform) | >= 1.0 | 115 | | [aws](#requirement\_aws) | >= 5.2 | 116 | 117 | ## Providers 118 | 119 | | Name | Version | 120 | |------|---------| 121 | | [aws](#provider\_aws) | >= 5.2 | 122 | 123 | ## Modules 124 | 125 | No modules. 126 | 127 | ## Resources 128 | 129 | | Name | Type | 130 | |------|------| 131 | | [aws_networkfirewall_resource_policy.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_resource_policy) | resource | 132 | | [aws_networkfirewall_rule_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_rule_group) | resource | 133 | | [aws_ram_resource_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ram_resource_association) | resource | 134 | | [aws_iam_policy_document.rule_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | 135 | 136 | ## Inputs 137 | 138 | | Name | Description | Type | Default | Required | 139 | |------|-------------|------|---------|:--------:| 140 | | [attach\_resource\_policy](#input\_attach\_resource\_policy) | Controls if a resource policy should be attached to the rule group | `bool` | `false` | no | 141 | | [capacity](#input\_capacity) | The maximum number of operating resources that this rule group can use. For a stateless rule group, the capacity required is the sum of the capacity requirements of the individual rules. For a stateful rule group, the minimum capacity required is the number of individual rules | `number` | `100` | no | 142 | | [create](#input\_create) | Controls if Network Firewall resources should be created | `bool` | `true` | no | 143 | | [create\_resource\_policy](#input\_create\_resource\_policy) | Controls if a resource policy should be created | `bool` | `false` | no | 144 | | [description](#input\_description) | A friendly description of the rule group | `string` | `null` | no | 145 | | [encryption\_configuration](#input\_encryption\_configuration) | KMS encryption configuration settings | `any` | `{}` | no | 146 | | [name](#input\_name) | A friendly name of the rule group | `string` | `""` | no | 147 | | [ram\_resource\_associations](#input\_ram\_resource\_associations) | A map of RAM resource associations for the created rule group | `map(string)` | `{}` | no | 148 | | [resource\_policy](#input\_resource\_policy) | The policy JSON to use for the resource policy; required when `create_resource_policy` is `false` | `string` | `""` | no | 149 | | [resource\_policy\_actions](#input\_resource\_policy\_actions) | A list of IAM actions allowed in the resource policy | `list(string)` | `[]` | no | 150 | | [resource\_policy\_principals](#input\_resource\_policy\_principals) | A list of IAM principals allowed in the resource policy | `list(string)` | `[]` | no | 151 | | [rule\_group](#input\_rule\_group) | A configuration block that defines the rule group rules. Required unless `rules` is specified | `any` | `{}` | no | 152 | | [rules](#input\_rules) | The stateful rule group rules specifications in Suricata file format, with one rule per line. Use this to import your existing Suricata compatible rule groups. Required unless `rule_group` is specified | `string` | `null` | no | 153 | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | 154 | | [type](#input\_type) | Whether the rule group is stateless (containing stateless rules) or stateful (containing stateful rules). Valid values include: `STATEFUL` or `STATELESS` | `string` | `"STATELESS"` | no | 155 | 156 | ## Outputs 157 | 158 | | Name | Description | 159 | |------|-------------| 160 | | [arn](#output\_arn) | The Amazon Resource Name (ARN) that identifies the rule group | 161 | | [id](#output\_id) | The Amazon Resource Name (ARN) that identifies the rule group | 162 | | [resource\_policy\_id](#output\_resource\_policy\_id) | The Amazon Resource Name (ARN) of the rule group associated with the resource policy | 163 | | [update\_token](#output\_update\_token) | A string token used when updating the rule group | 164 | 165 | 166 | ## License 167 | 168 | Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-network-firewall/blob/master/LICENSE). 169 | -------------------------------------------------------------------------------- /modules/rule-group/main.tf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Rule Group 3 | ################################################################################ 4 | 5 | resource "aws_networkfirewall_rule_group" "this" { 6 | count = var.create ? 1 : 0 7 | 8 | capacity = var.capacity 9 | description = var.description 10 | 11 | dynamic "encryption_configuration" { 12 | for_each = length(var.encryption_configuration) > 0 ? [var.encryption_configuration] : [] 13 | 14 | content { 15 | key_id = try(encryption_configuration.value.key_id, null) 16 | type = encryption_configuration.value.type 17 | } 18 | } 19 | 20 | name = var.name 21 | 22 | dynamic "rule_group" { 23 | for_each = length(var.rule_group) > 0 ? [var.rule_group] : [] 24 | 25 | content { 26 | 27 | dynamic "rule_variables" { 28 | for_each = try([rule_group.value.rule_variables], []) 29 | content { 30 | 31 | dynamic "ip_sets" { 32 | # One or more 33 | for_each = try(rule_variables.value.ip_sets, []) 34 | content { 35 | key = ip_sets.value.key 36 | dynamic "ip_set" { 37 | for_each = [ip_sets.value.ip_set] 38 | content { 39 | definition = ip_set.value.definition 40 | } 41 | } 42 | } 43 | } 44 | 45 | dynamic "port_sets" { 46 | # One or more 47 | for_each = try(rule_variables.value.port_sets, []) 48 | content { 49 | key = port_sets.value.key 50 | dynamic "port_set" { 51 | for_each = [port_sets.value.port_set] 52 | content { 53 | definition = port_set.value.definition 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } 60 | 61 | dynamic "rules_source" { 62 | for_each = [rule_group.value.rules_source] 63 | content { 64 | rules_string = try(rules_source.value.rules_string, null) 65 | 66 | dynamic "rules_source_list" { 67 | for_each = try([rules_source.value.rules_source_list], []) 68 | content { 69 | generated_rules_type = rules_source_list.value.generated_rules_type 70 | target_types = rules_source_list.value.target_types 71 | targets = rules_source_list.value.targets 72 | } 73 | } 74 | 75 | dynamic "stateful_rule" { 76 | # One or more 77 | for_each = try(rules_source.value.stateful_rule, []) 78 | content { 79 | action = stateful_rule.value.action 80 | 81 | dynamic "header" { 82 | for_each = [stateful_rule.value.header] 83 | content { 84 | destination = header.value.destination 85 | destination_port = header.value.destination_port 86 | direction = header.value.direction 87 | protocol = header.value.protocol 88 | source = header.value.source 89 | source_port = header.value.source_port 90 | } 91 | } 92 | 93 | dynamic "rule_option" { 94 | # One or more 95 | for_each = stateful_rule.value.rule_option 96 | content { 97 | keyword = rule_option.value.keyword 98 | settings = try(rule_option.value.settings, null) 99 | } 100 | } 101 | } 102 | } 103 | 104 | dynamic "stateless_rules_and_custom_actions" { 105 | for_each = try([rules_source.value.stateless_rules_and_custom_actions], []) 106 | content { 107 | 108 | dynamic "custom_action" { 109 | # One or more 110 | for_each = try(stateless_rules_and_custom_actions.value.custom_action, []) 111 | content { 112 | action_name = custom_action.value.action_name 113 | 114 | dynamic "action_definition" { 115 | for_each = [custom_action.value.action_definition] 116 | content { 117 | dynamic "publish_metric_action" { 118 | for_each = [action_definition.value.publish_metric_action] 119 | content { 120 | dynamic "dimension" { 121 | # One or more 122 | for_each = publish_metric_action.value.dimension 123 | content { 124 | value = dimension.value.value 125 | } 126 | } 127 | } 128 | } 129 | } 130 | } 131 | } 132 | } 133 | 134 | dynamic "stateless_rule" { 135 | # One or more 136 | for_each = stateless_rules_and_custom_actions.value.stateless_rule 137 | content { 138 | priority = stateless_rule.value.priority 139 | 140 | dynamic "rule_definition" { 141 | for_each = [stateless_rule.value.rule_definition] 142 | content { 143 | actions = rule_definition.value.actions 144 | 145 | dynamic "match_attributes" { 146 | for_each = [rule_definition.value.match_attributes] 147 | content { 148 | 149 | protocols = try(match_attributes.value.protocols, []) 150 | 151 | dynamic "destination" { 152 | # One or more 153 | for_each = try(match_attributes.value.destination, []) 154 | content { 155 | address_definition = destination.value.address_definition 156 | } 157 | } 158 | 159 | dynamic "destination_port" { 160 | # One or more 161 | for_each = try(match_attributes.value.destination_port, []) 162 | content { 163 | from_port = destination_port.value.from_port 164 | to_port = try(destination_port.value.to_port, null) 165 | } 166 | } 167 | 168 | dynamic "source" { 169 | # One or more 170 | for_each = try(match_attributes.value.source, []) 171 | content { 172 | address_definition = source.value.address_definition 173 | } 174 | } 175 | 176 | dynamic "source_port" { 177 | # One or more 178 | for_each = try(match_attributes.value.source_port, []) 179 | content { 180 | from_port = source_port.value.from_port 181 | to_port = try(source_port.value.to_port, null) 182 | } 183 | } 184 | 185 | dynamic "tcp_flag" { 186 | # One or more 187 | for_each = try(match_attributes.value.tcp_flag, []) 188 | content { 189 | flags = tcp_flag.value.flags 190 | masks = try(tcp_flag.value.masks, []) 191 | } 192 | } 193 | } 194 | } 195 | } 196 | } 197 | } 198 | } 199 | } 200 | } 201 | } 202 | } 203 | 204 | dynamic "stateful_rule_options" { 205 | for_each = try([rule_group.value.stateful_rule_options], []) 206 | content { 207 | rule_order = stateful_rule_options.value.rule_order 208 | } 209 | } 210 | } 211 | } 212 | 213 | rules = var.rules 214 | type = var.type 215 | 216 | tags = var.tags 217 | } 218 | 219 | ################################################################################ 220 | # Resource Policy 221 | ################################################################################ 222 | 223 | data "aws_iam_policy_document" "rule_group" { 224 | count = var.create && var.create_resource_policy ? 1 : 0 225 | 226 | statement { 227 | sid = "RuleGroupResourcePolicy" 228 | actions = distinct(concat( 229 | var.resource_policy_actions, 230 | [ 231 | "network-firewall:ListRuleGroups", 232 | "network-firewall:CreateFirewallPolicy", 233 | "network-firewall:UpdateFirewallPolicy", 234 | ] 235 | )) 236 | resources = [aws_networkfirewall_rule_group.this[0].arn] 237 | 238 | principals { 239 | type = "AWS" 240 | identifiers = var.resource_policy_principals 241 | } 242 | } 243 | } 244 | 245 | resource "aws_networkfirewall_resource_policy" "this" { 246 | count = var.create && var.attach_resource_policy ? 1 : 0 247 | 248 | resource_arn = aws_networkfirewall_rule_group.this[0].arn 249 | policy = var.create_resource_policy ? data.aws_iam_policy_document.rule_group[0].json : var.resource_policy 250 | } 251 | 252 | ################################################################################ 253 | # RAM Resource Association 254 | ################################################################################ 255 | 256 | resource "aws_ram_resource_association" "this" { 257 | for_each = { for k, v in var.ram_resource_associations : k => v if var.create } 258 | 259 | resource_arn = aws_networkfirewall_rule_group.this[0].arn 260 | resource_share_arn = each.value.resource_share_arn 261 | } 262 | -------------------------------------------------------------------------------- /modules/rule-group/outputs.tf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Rule Group 3 | ################################################################################ 4 | 5 | output "id" { 6 | description = "The Amazon Resource Name (ARN) that identifies the rule group" 7 | value = try(aws_networkfirewall_rule_group.this[0].id, null) 8 | } 9 | 10 | output "arn" { 11 | description = "The Amazon Resource Name (ARN) that identifies the rule group" 12 | value = try(aws_networkfirewall_rule_group.this[0].arn, null) 13 | } 14 | 15 | output "update_token" { 16 | description = "A string token used when updating the rule group" 17 | value = try(aws_networkfirewall_rule_group.this[0].update_token, null) 18 | } 19 | 20 | ################################################################################ 21 | # Resource Policy 22 | ################################################################################ 23 | 24 | output "resource_policy_id" { 25 | description = "The Amazon Resource Name (ARN) of the rule group associated with the resource policy" 26 | value = try(aws_networkfirewall_resource_policy.this[0].id, null) 27 | } 28 | -------------------------------------------------------------------------------- /modules/rule-group/variables.tf: -------------------------------------------------------------------------------- 1 | variable "create" { 2 | description = "Controls if Network Firewall resources should be created" 3 | type = bool 4 | default = true 5 | } 6 | 7 | variable "tags" { 8 | description = "A map of tags to add to all resources" 9 | type = map(string) 10 | default = {} 11 | } 12 | 13 | ################################################################################ 14 | # Rule Group 15 | ################################################################################ 16 | 17 | variable "capacity" { 18 | description = "The maximum number of operating resources that this rule group can use. For a stateless rule group, the capacity required is the sum of the capacity requirements of the individual rules. For a stateful rule group, the minimum capacity required is the number of individual rules" 19 | type = number 20 | default = 100 21 | } 22 | 23 | variable "description" { 24 | description = "A friendly description of the rule group" 25 | type = string 26 | default = null 27 | } 28 | 29 | variable "encryption_configuration" { 30 | description = "KMS encryption configuration settings" 31 | type = any 32 | default = {} 33 | } 34 | 35 | variable "name" { 36 | description = "A friendly name of the rule group" 37 | type = string 38 | default = "" 39 | } 40 | 41 | variable "rule_group" { 42 | description = "A configuration block that defines the rule group rules. Required unless `rules` is specified" 43 | type = any 44 | default = {} 45 | } 46 | 47 | variable "rules" { 48 | description = "The stateful rule group rules specifications in Suricata file format, with one rule per line. Use this to import your existing Suricata compatible rule groups. Required unless `rule_group` is specified" 49 | type = string 50 | default = null 51 | } 52 | 53 | variable "type" { 54 | description = "Whether the rule group is stateless (containing stateless rules) or stateful (containing stateful rules). Valid values include: `STATEFUL` or `STATELESS`" 55 | type = string 56 | default = "STATELESS" 57 | } 58 | 59 | ################################################################################ 60 | # Resource Policy 61 | ################################################################################ 62 | 63 | variable "create_resource_policy" { 64 | description = "Controls if a resource policy should be created" 65 | type = bool 66 | default = false 67 | } 68 | 69 | variable "resource_policy_actions" { 70 | description = "A list of IAM actions allowed in the resource policy" 71 | type = list(string) 72 | default = [] 73 | } 74 | 75 | variable "resource_policy_principals" { 76 | description = "A list of IAM principals allowed in the resource policy" 77 | type = list(string) 78 | default = [] 79 | } 80 | 81 | variable "attach_resource_policy" { 82 | description = "Controls if a resource policy should be attached to the rule group" 83 | type = bool 84 | default = false 85 | } 86 | 87 | variable "resource_policy" { 88 | description = "The policy JSON to use for the resource policy; required when `create_resource_policy` is `false`" 89 | type = string 90 | default = "" 91 | } 92 | 93 | ################################################################################ 94 | # RAM Resource Association 95 | ################################################################################ 96 | 97 | variable "ram_resource_associations" { 98 | description = "A map of RAM resource associations for the created rule group" 99 | type = map(string) 100 | default = {} 101 | } 102 | -------------------------------------------------------------------------------- /modules/rule-group/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 5.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Firewall 3 | ################################################################################ 4 | 5 | output "id" { 6 | description = "The Amazon Resource Name (ARN) that identifies the firewall" 7 | value = module.firewall.id 8 | } 9 | 10 | output "arn" { 11 | description = "The Amazon Resource Name (ARN) that identifies the firewall" 12 | value = module.firewall.arn 13 | } 14 | 15 | output "status" { 16 | description = "Nested list of information about the current status of the firewall" 17 | value = module.firewall.status 18 | } 19 | 20 | output "update_token" { 21 | description = "A string token used when updating a firewall" 22 | value = module.firewall.update_token 23 | } 24 | 25 | ################################################################################ 26 | # Firewall Logging Configuration 27 | ################################################################################ 28 | 29 | output "logging_configuration_id" { 30 | description = "The Amazon Resource Name (ARN) of the associated firewall" 31 | value = module.firewall.logging_configuration_id 32 | } 33 | 34 | ################################################################################ 35 | # Firewall Policy 36 | ################################################################################ 37 | 38 | output "policy_id" { 39 | description = "The Amazon Resource Name (ARN) that identifies the firewall policy" 40 | value = module.policy.id 41 | } 42 | 43 | output "policy_arn" { 44 | description = "The Amazon Resource Name (ARN) that identifies the firewall policy" 45 | value = module.policy.arn 46 | } 47 | 48 | output "policy_update_token" { 49 | description = "A string token used when updating a firewall policy" 50 | value = module.policy.update_token 51 | } 52 | 53 | output "policy_resource_policy_id" { 54 | description = "The Amazon Resource Name (ARN) of the firewall policy associated with the resource policy" 55 | value = module.policy.resource_policy_id 56 | } 57 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | variable "create" { 2 | description = "Controls if resources should be created" 3 | type = bool 4 | default = true 5 | } 6 | 7 | variable "tags" { 8 | description = "A map of tags to add to all resources" 9 | type = map(string) 10 | default = {} 11 | } 12 | 13 | ################################################################################ 14 | # Firewall 15 | ################################################################################ 16 | 17 | variable "delete_protection" { 18 | description = "A boolean flag indicating whether it is possible to delete the firewall. Defaults to `true`" 19 | type = bool 20 | default = true 21 | } 22 | 23 | variable "description" { 24 | description = "A friendly description of the firewall" 25 | type = string 26 | default = "" 27 | } 28 | 29 | variable "encryption_configuration" { 30 | description = "KMS encryption configuration settings" 31 | type = any 32 | default = {} 33 | } 34 | 35 | variable "firewall_policy_arn" { 36 | description = "The ARN of the Firewall Policy to use" 37 | type = string 38 | default = "" 39 | } 40 | 41 | variable "firewall_policy_change_protection" { 42 | description = "A boolean flag indicating whether it is possible to change the associated firewall policy. Defaults to `false`" 43 | type = bool 44 | default = null 45 | } 46 | 47 | variable "name" { 48 | description = "A friendly name of the firewall" 49 | type = string 50 | default = "" 51 | } 52 | 53 | variable "subnet_change_protection" { 54 | description = "A boolean flag indicating whether it is possible to change the associated subnet(s). Defaults to `true`" 55 | type = bool 56 | default = true 57 | } 58 | 59 | variable "subnet_mapping" { 60 | description = "Set of configuration blocks describing the public subnets. Each subnet must belong to a different Availability Zone in the VPC. AWS Network Firewall creates a firewall endpoint in each subnet" 61 | type = any 62 | default = {} 63 | } 64 | 65 | variable "vpc_id" { 66 | description = "The unique identifier of the VPC where AWS Network Firewall should create the firewall" 67 | type = string 68 | default = "" 69 | } 70 | 71 | ################################################################################ 72 | # Firewall Logging Configuration 73 | ################################################################################ 74 | 75 | variable "create_logging_configuration" { 76 | description = "Controls if a Logging Configuration should be created" 77 | type = bool 78 | default = false 79 | } 80 | 81 | variable "logging_configuration_destination_config" { 82 | description = "A list of min 1, max 2 configuration blocks describing the destination for the logging configuration" 83 | type = any 84 | default = [] 85 | } 86 | ################################################################################ 87 | # Firewall Policy 88 | ################################################################################ 89 | 90 | variable "create_policy" { 91 | description = "Controls if policy should be created" 92 | type = bool 93 | default = true 94 | } 95 | 96 | variable "policy_description" { 97 | description = "A friendly description of the firewall policy" 98 | type = string 99 | default = null 100 | } 101 | 102 | variable "policy_encryption_configuration" { 103 | description = "KMS encryption configuration settings" 104 | type = any 105 | default = {} 106 | } 107 | 108 | variable "policy_stateful_default_actions" { 109 | description = "Set of actions to take on a packet if it does not match any stateful rules in the policy. This can only be specified if the policy has a `stateful_engine_options` block with a rule_order value of `STRICT_ORDER`. You can specify one of either or neither values of `aws:drop_strict` or `aws:drop_established`, as well as any combination of `aws:alert_strict` and `aws:alert_established`" 110 | type = list(string) 111 | default = [] 112 | } 113 | 114 | variable "policy_stateful_engine_options" { 115 | description = "A configuration block that defines options on how the policy handles stateful rules. See [Stateful Engine Options](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy#stateful-engine-options) for details" 116 | type = any 117 | default = {} 118 | } 119 | 120 | variable "policy_stateful_rule_group_reference" { 121 | description = "Set of configuration blocks containing references to the stateful rule groups that are used in the policy. See [Stateful Rule Group Reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy#stateful-rule-group-reference) for details" 122 | type = any 123 | default = {} 124 | } 125 | 126 | variable "policy_stateless_custom_action" { 127 | description = "Set of configuration blocks describing the custom action definitions that are available for use in the firewall policy's `stateless_default_actions`" 128 | type = any 129 | default = {} 130 | } 131 | 132 | variable "policy_stateless_default_actions" { 133 | description = "Set of actions to take on a packet if it does not match any of the stateless rules in the policy. You must specify one of the standard actions including: `aws:drop`, `aws:pass`, or `aws:forward_to_sfe`" 134 | type = list(string) 135 | default = ["aws:pass"] 136 | } 137 | 138 | variable "policy_stateless_fragment_default_actions" { 139 | description = "Set of actions to take on a fragmented packet if it does not match any of the stateless rules in the policy. You must specify one of the standard actions including: `aws:drop`, `aws:pass`, or `aws:forward_to_sfe`" 140 | type = list(string) 141 | default = ["aws:pass"] 142 | } 143 | 144 | variable "policy_stateless_rule_group_reference" { 145 | description = "Set of configuration blocks containing references to the stateless rule groups that are used in the policy. See [Stateless Rule Group Reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/networkfirewall_firewall_policy#stateless-rule-group-reference) for details" 146 | type = any 147 | default = {} 148 | } 149 | 150 | variable "policy_name" { 151 | description = "A friendly name of the firewall policy" 152 | type = string 153 | default = "" 154 | } 155 | 156 | variable "policy_tags" { 157 | description = "A map of tags to add to all resources" 158 | type = map(string) 159 | default = {} 160 | } 161 | 162 | # Resource Policy 163 | variable "create_policy_resource_policy" { 164 | description = "Controls if a resource policy should be created" 165 | type = bool 166 | default = false 167 | } 168 | 169 | variable "policy_resource_policy_actions" { 170 | description = "A list of IAM actions allowed in the resource policy" 171 | type = list(string) 172 | default = [] 173 | } 174 | 175 | variable "policy_resource_policy_principals" { 176 | description = "A list of IAM principals allowed in the resource policy" 177 | type = list(string) 178 | default = [] 179 | } 180 | 181 | variable "policy_attach_resource_policy" { 182 | description = "Controls if a resource policy should be attached to the firewall policy" 183 | type = bool 184 | default = false 185 | } 186 | 187 | variable "policy_resource_policy" { 188 | description = "The policy JSON to use for the resource policy; required when `create_resource_policy` is `false`" 189 | type = string 190 | default = "" 191 | } 192 | 193 | # RAM Resource Association 194 | variable "policy_ram_resource_associations" { 195 | description = "A map of RAM resource associations for the created firewall policy" 196 | type = map(string) 197 | default = {} 198 | } 199 | -------------------------------------------------------------------------------- /versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0" 3 | } 4 | -------------------------------------------------------------------------------- /wrappers/README.md: -------------------------------------------------------------------------------- 1 | # Wrapper for the root module 2 | 3 | The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt). 4 | 5 | You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module. 6 | 7 | This wrapper does not implement any extra functionality. 8 | 9 | ## Usage with Terragrunt 10 | 11 | `terragrunt.hcl`: 12 | 13 | ```hcl 14 | terraform { 15 | source = "tfr:///terraform-aws-modules/network-firewall/aws//wrappers" 16 | # Alternative source: 17 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-network-firewall.git//wrappers?ref=master" 18 | } 19 | 20 | inputs = { 21 | defaults = { # Default values 22 | create = true 23 | tags = { 24 | Terraform = "true" 25 | Environment = "dev" 26 | } 27 | } 28 | 29 | items = { 30 | my-item = { 31 | # omitted... can be any argument supported by the module 32 | } 33 | my-second-item = { 34 | # omitted... can be any argument supported by the module 35 | } 36 | # omitted... 37 | } 38 | } 39 | ``` 40 | 41 | ## Usage with Terraform 42 | 43 | ```hcl 44 | module "wrapper" { 45 | source = "terraform-aws-modules/network-firewall/aws//wrappers" 46 | 47 | defaults = { # Default values 48 | create = true 49 | tags = { 50 | Terraform = "true" 51 | Environment = "dev" 52 | } 53 | } 54 | 55 | items = { 56 | my-item = { 57 | # omitted... can be any argument supported by the module 58 | } 59 | my-second-item = { 60 | # omitted... can be any argument supported by the module 61 | } 62 | # omitted... 63 | } 64 | } 65 | ``` 66 | 67 | ## Example: Manage multiple S3 buckets in one Terragrunt layer 68 | 69 | `eu-west-1/s3-buckets/terragrunt.hcl`: 70 | 71 | ```hcl 72 | terraform { 73 | source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers" 74 | # Alternative source: 75 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master" 76 | } 77 | 78 | inputs = { 79 | defaults = { 80 | force_destroy = true 81 | 82 | attach_elb_log_delivery_policy = true 83 | attach_lb_log_delivery_policy = true 84 | attach_deny_insecure_transport_policy = true 85 | attach_require_latest_tls_policy = true 86 | } 87 | 88 | items = { 89 | bucket1 = { 90 | bucket = "my-random-bucket-1" 91 | } 92 | bucket2 = { 93 | bucket = "my-random-bucket-2" 94 | tags = { 95 | Secure = "probably" 96 | } 97 | } 98 | } 99 | } 100 | ``` 101 | -------------------------------------------------------------------------------- /wrappers/firewall/README.md: -------------------------------------------------------------------------------- 1 | # Wrapper for module: `modules/firewall` 2 | 3 | The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt). 4 | 5 | You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module. 6 | 7 | This wrapper does not implement any extra functionality. 8 | 9 | ## Usage with Terragrunt 10 | 11 | `terragrunt.hcl`: 12 | 13 | ```hcl 14 | terraform { 15 | source = "tfr:///terraform-aws-modules/network-firewall/aws//wrappers/firewall" 16 | # Alternative source: 17 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-network-firewall.git//wrappers/firewall?ref=master" 18 | } 19 | 20 | inputs = { 21 | defaults = { # Default values 22 | create = true 23 | tags = { 24 | Terraform = "true" 25 | Environment = "dev" 26 | } 27 | } 28 | 29 | items = { 30 | my-item = { 31 | # omitted... can be any argument supported by the module 32 | } 33 | my-second-item = { 34 | # omitted... can be any argument supported by the module 35 | } 36 | # omitted... 37 | } 38 | } 39 | ``` 40 | 41 | ## Usage with Terraform 42 | 43 | ```hcl 44 | module "wrapper" { 45 | source = "terraform-aws-modules/network-firewall/aws//wrappers/firewall" 46 | 47 | defaults = { # Default values 48 | create = true 49 | tags = { 50 | Terraform = "true" 51 | Environment = "dev" 52 | } 53 | } 54 | 55 | items = { 56 | my-item = { 57 | # omitted... can be any argument supported by the module 58 | } 59 | my-second-item = { 60 | # omitted... can be any argument supported by the module 61 | } 62 | # omitted... 63 | } 64 | } 65 | ``` 66 | 67 | ## Example: Manage multiple S3 buckets in one Terragrunt layer 68 | 69 | `eu-west-1/s3-buckets/terragrunt.hcl`: 70 | 71 | ```hcl 72 | terraform { 73 | source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers" 74 | # Alternative source: 75 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master" 76 | } 77 | 78 | inputs = { 79 | defaults = { 80 | force_destroy = true 81 | 82 | attach_elb_log_delivery_policy = true 83 | attach_lb_log_delivery_policy = true 84 | attach_deny_insecure_transport_policy = true 85 | attach_require_latest_tls_policy = true 86 | } 87 | 88 | items = { 89 | bucket1 = { 90 | bucket = "my-random-bucket-1" 91 | } 92 | bucket2 = { 93 | bucket = "my-random-bucket-2" 94 | tags = { 95 | Secure = "probably" 96 | } 97 | } 98 | } 99 | } 100 | ``` 101 | -------------------------------------------------------------------------------- /wrappers/firewall/main.tf: -------------------------------------------------------------------------------- 1 | module "wrapper" { 2 | source = "../../modules/firewall" 3 | 4 | for_each = var.items 5 | 6 | create = try(each.value.create, var.defaults.create, true) 7 | create_logging_configuration = try(each.value.create_logging_configuration, var.defaults.create_logging_configuration, false) 8 | delete_protection = try(each.value.delete_protection, var.defaults.delete_protection, true) 9 | description = try(each.value.description, var.defaults.description, "") 10 | encryption_configuration = try(each.value.encryption_configuration, var.defaults.encryption_configuration, {}) 11 | firewall_policy_arn = try(each.value.firewall_policy_arn, var.defaults.firewall_policy_arn, "") 12 | firewall_policy_change_protection = try(each.value.firewall_policy_change_protection, var.defaults.firewall_policy_change_protection, null) 13 | logging_configuration_destination_config = try(each.value.logging_configuration_destination_config, var.defaults.logging_configuration_destination_config, []) 14 | name = try(each.value.name, var.defaults.name, "") 15 | subnet_change_protection = try(each.value.subnet_change_protection, var.defaults.subnet_change_protection, true) 16 | subnet_mapping = try(each.value.subnet_mapping, var.defaults.subnet_mapping, {}) 17 | tags = try(each.value.tags, var.defaults.tags, {}) 18 | vpc_id = try(each.value.vpc_id, var.defaults.vpc_id, "") 19 | } 20 | -------------------------------------------------------------------------------- /wrappers/firewall/outputs.tf: -------------------------------------------------------------------------------- 1 | output "wrapper" { 2 | description = "Map of outputs of a wrapper." 3 | value = module.wrapper 4 | # sensitive = false # No sensitive module output found 5 | } 6 | -------------------------------------------------------------------------------- /wrappers/firewall/variables.tf: -------------------------------------------------------------------------------- 1 | variable "defaults" { 2 | description = "Map of default values which will be used for each item." 3 | type = any 4 | default = {} 5 | } 6 | 7 | variable "items" { 8 | description = "Maps of items to create a wrapper from. Values are passed through to the module." 9 | type = any 10 | default = {} 11 | } 12 | -------------------------------------------------------------------------------- /wrappers/firewall/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 5.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /wrappers/main.tf: -------------------------------------------------------------------------------- 1 | module "wrapper" { 2 | source = "../" 3 | 4 | for_each = var.items 5 | 6 | create = try(each.value.create, var.defaults.create, true) 7 | create_logging_configuration = try(each.value.create_logging_configuration, var.defaults.create_logging_configuration, false) 8 | create_policy = try(each.value.create_policy, var.defaults.create_policy, true) 9 | create_policy_resource_policy = try(each.value.create_policy_resource_policy, var.defaults.create_policy_resource_policy, false) 10 | delete_protection = try(each.value.delete_protection, var.defaults.delete_protection, true) 11 | description = try(each.value.description, var.defaults.description, "") 12 | encryption_configuration = try(each.value.encryption_configuration, var.defaults.encryption_configuration, {}) 13 | firewall_policy_arn = try(each.value.firewall_policy_arn, var.defaults.firewall_policy_arn, "") 14 | firewall_policy_change_protection = try(each.value.firewall_policy_change_protection, var.defaults.firewall_policy_change_protection, null) 15 | logging_configuration_destination_config = try(each.value.logging_configuration_destination_config, var.defaults.logging_configuration_destination_config, []) 16 | name = try(each.value.name, var.defaults.name, "") 17 | policy_attach_resource_policy = try(each.value.policy_attach_resource_policy, var.defaults.policy_attach_resource_policy, false) 18 | policy_description = try(each.value.policy_description, var.defaults.policy_description, null) 19 | policy_encryption_configuration = try(each.value.policy_encryption_configuration, var.defaults.policy_encryption_configuration, {}) 20 | policy_name = try(each.value.policy_name, var.defaults.policy_name, "") 21 | policy_ram_resource_associations = try(each.value.policy_ram_resource_associations, var.defaults.policy_ram_resource_associations, {}) 22 | policy_resource_policy = try(each.value.policy_resource_policy, var.defaults.policy_resource_policy, "") 23 | policy_resource_policy_actions = try(each.value.policy_resource_policy_actions, var.defaults.policy_resource_policy_actions, []) 24 | policy_resource_policy_principals = try(each.value.policy_resource_policy_principals, var.defaults.policy_resource_policy_principals, []) 25 | policy_stateful_default_actions = try(each.value.policy_stateful_default_actions, var.defaults.policy_stateful_default_actions, []) 26 | policy_stateful_engine_options = try(each.value.policy_stateful_engine_options, var.defaults.policy_stateful_engine_options, {}) 27 | policy_stateful_rule_group_reference = try(each.value.policy_stateful_rule_group_reference, var.defaults.policy_stateful_rule_group_reference, {}) 28 | policy_stateless_custom_action = try(each.value.policy_stateless_custom_action, var.defaults.policy_stateless_custom_action, {}) 29 | policy_stateless_default_actions = try(each.value.policy_stateless_default_actions, var.defaults.policy_stateless_default_actions, ["aws:pass"]) 30 | policy_stateless_fragment_default_actions = try(each.value.policy_stateless_fragment_default_actions, var.defaults.policy_stateless_fragment_default_actions, ["aws:pass"]) 31 | policy_stateless_rule_group_reference = try(each.value.policy_stateless_rule_group_reference, var.defaults.policy_stateless_rule_group_reference, {}) 32 | policy_tags = try(each.value.policy_tags, var.defaults.policy_tags, {}) 33 | subnet_change_protection = try(each.value.subnet_change_protection, var.defaults.subnet_change_protection, true) 34 | subnet_mapping = try(each.value.subnet_mapping, var.defaults.subnet_mapping, {}) 35 | tags = try(each.value.tags, var.defaults.tags, {}) 36 | vpc_id = try(each.value.vpc_id, var.defaults.vpc_id, "") 37 | } 38 | -------------------------------------------------------------------------------- /wrappers/outputs.tf: -------------------------------------------------------------------------------- 1 | output "wrapper" { 2 | description = "Map of outputs of a wrapper." 3 | value = module.wrapper 4 | # sensitive = false # No sensitive module output found 5 | } 6 | -------------------------------------------------------------------------------- /wrappers/policy/README.md: -------------------------------------------------------------------------------- 1 | # Wrapper for module: `modules/policy` 2 | 3 | The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt). 4 | 5 | You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module. 6 | 7 | This wrapper does not implement any extra functionality. 8 | 9 | ## Usage with Terragrunt 10 | 11 | `terragrunt.hcl`: 12 | 13 | ```hcl 14 | terraform { 15 | source = "tfr:///terraform-aws-modules/network-firewall/aws//wrappers/policy" 16 | # Alternative source: 17 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-network-firewall.git//wrappers/policy?ref=master" 18 | } 19 | 20 | inputs = { 21 | defaults = { # Default values 22 | create = true 23 | tags = { 24 | Terraform = "true" 25 | Environment = "dev" 26 | } 27 | } 28 | 29 | items = { 30 | my-item = { 31 | # omitted... can be any argument supported by the module 32 | } 33 | my-second-item = { 34 | # omitted... can be any argument supported by the module 35 | } 36 | # omitted... 37 | } 38 | } 39 | ``` 40 | 41 | ## Usage with Terraform 42 | 43 | ```hcl 44 | module "wrapper" { 45 | source = "terraform-aws-modules/network-firewall/aws//wrappers/policy" 46 | 47 | defaults = { # Default values 48 | create = true 49 | tags = { 50 | Terraform = "true" 51 | Environment = "dev" 52 | } 53 | } 54 | 55 | items = { 56 | my-item = { 57 | # omitted... can be any argument supported by the module 58 | } 59 | my-second-item = { 60 | # omitted... can be any argument supported by the module 61 | } 62 | # omitted... 63 | } 64 | } 65 | ``` 66 | 67 | ## Example: Manage multiple S3 buckets in one Terragrunt layer 68 | 69 | `eu-west-1/s3-buckets/terragrunt.hcl`: 70 | 71 | ```hcl 72 | terraform { 73 | source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers" 74 | # Alternative source: 75 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master" 76 | } 77 | 78 | inputs = { 79 | defaults = { 80 | force_destroy = true 81 | 82 | attach_elb_log_delivery_policy = true 83 | attach_lb_log_delivery_policy = true 84 | attach_deny_insecure_transport_policy = true 85 | attach_require_latest_tls_policy = true 86 | } 87 | 88 | items = { 89 | bucket1 = { 90 | bucket = "my-random-bucket-1" 91 | } 92 | bucket2 = { 93 | bucket = "my-random-bucket-2" 94 | tags = { 95 | Secure = "probably" 96 | } 97 | } 98 | } 99 | } 100 | ``` 101 | -------------------------------------------------------------------------------- /wrappers/policy/main.tf: -------------------------------------------------------------------------------- 1 | module "wrapper" { 2 | source = "../../modules/policy" 3 | 4 | for_each = var.items 5 | 6 | attach_resource_policy = try(each.value.attach_resource_policy, var.defaults.attach_resource_policy, false) 7 | create = try(each.value.create, var.defaults.create, true) 8 | create_resource_policy = try(each.value.create_resource_policy, var.defaults.create_resource_policy, false) 9 | description = try(each.value.description, var.defaults.description, null) 10 | encryption_configuration = try(each.value.encryption_configuration, var.defaults.encryption_configuration, {}) 11 | name = try(each.value.name, var.defaults.name, "") 12 | ram_resource_associations = try(each.value.ram_resource_associations, var.defaults.ram_resource_associations, {}) 13 | resource_policy = try(each.value.resource_policy, var.defaults.resource_policy, "") 14 | resource_policy_actions = try(each.value.resource_policy_actions, var.defaults.resource_policy_actions, []) 15 | resource_policy_principals = try(each.value.resource_policy_principals, var.defaults.resource_policy_principals, []) 16 | stateful_default_actions = try(each.value.stateful_default_actions, var.defaults.stateful_default_actions, []) 17 | stateful_engine_options = try(each.value.stateful_engine_options, var.defaults.stateful_engine_options, {}) 18 | stateful_rule_group_reference = try(each.value.stateful_rule_group_reference, var.defaults.stateful_rule_group_reference, {}) 19 | stateless_custom_action = try(each.value.stateless_custom_action, var.defaults.stateless_custom_action, {}) 20 | stateless_default_actions = try(each.value.stateless_default_actions, var.defaults.stateless_default_actions, ["aws:pass"]) 21 | stateless_fragment_default_actions = try(each.value.stateless_fragment_default_actions, var.defaults.stateless_fragment_default_actions, ["aws:pass"]) 22 | stateless_rule_group_reference = try(each.value.stateless_rule_group_reference, var.defaults.stateless_rule_group_reference, {}) 23 | tags = try(each.value.tags, var.defaults.tags, {}) 24 | } 25 | -------------------------------------------------------------------------------- /wrappers/policy/outputs.tf: -------------------------------------------------------------------------------- 1 | output "wrapper" { 2 | description = "Map of outputs of a wrapper." 3 | value = module.wrapper 4 | # sensitive = false # No sensitive module output found 5 | } 6 | -------------------------------------------------------------------------------- /wrappers/policy/variables.tf: -------------------------------------------------------------------------------- 1 | variable "defaults" { 2 | description = "Map of default values which will be used for each item." 3 | type = any 4 | default = {} 5 | } 6 | 7 | variable "items" { 8 | description = "Maps of items to create a wrapper from. Values are passed through to the module." 9 | type = any 10 | default = {} 11 | } 12 | -------------------------------------------------------------------------------- /wrappers/policy/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 5.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /wrappers/rule-group/README.md: -------------------------------------------------------------------------------- 1 | # Wrapper for module: `modules/rule-group` 2 | 3 | The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt). 4 | 5 | You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module. 6 | 7 | This wrapper does not implement any extra functionality. 8 | 9 | ## Usage with Terragrunt 10 | 11 | `terragrunt.hcl`: 12 | 13 | ```hcl 14 | terraform { 15 | source = "tfr:///terraform-aws-modules/network-firewall/aws//wrappers/rule-group" 16 | # Alternative source: 17 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-network-firewall.git//wrappers/rule-group?ref=master" 18 | } 19 | 20 | inputs = { 21 | defaults = { # Default values 22 | create = true 23 | tags = { 24 | Terraform = "true" 25 | Environment = "dev" 26 | } 27 | } 28 | 29 | items = { 30 | my-item = { 31 | # omitted... can be any argument supported by the module 32 | } 33 | my-second-item = { 34 | # omitted... can be any argument supported by the module 35 | } 36 | # omitted... 37 | } 38 | } 39 | ``` 40 | 41 | ## Usage with Terraform 42 | 43 | ```hcl 44 | module "wrapper" { 45 | source = "terraform-aws-modules/network-firewall/aws//wrappers/rule-group" 46 | 47 | defaults = { # Default values 48 | create = true 49 | tags = { 50 | Terraform = "true" 51 | Environment = "dev" 52 | } 53 | } 54 | 55 | items = { 56 | my-item = { 57 | # omitted... can be any argument supported by the module 58 | } 59 | my-second-item = { 60 | # omitted... can be any argument supported by the module 61 | } 62 | # omitted... 63 | } 64 | } 65 | ``` 66 | 67 | ## Example: Manage multiple S3 buckets in one Terragrunt layer 68 | 69 | `eu-west-1/s3-buckets/terragrunt.hcl`: 70 | 71 | ```hcl 72 | terraform { 73 | source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers" 74 | # Alternative source: 75 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master" 76 | } 77 | 78 | inputs = { 79 | defaults = { 80 | force_destroy = true 81 | 82 | attach_elb_log_delivery_policy = true 83 | attach_lb_log_delivery_policy = true 84 | attach_deny_insecure_transport_policy = true 85 | attach_require_latest_tls_policy = true 86 | } 87 | 88 | items = { 89 | bucket1 = { 90 | bucket = "my-random-bucket-1" 91 | } 92 | bucket2 = { 93 | bucket = "my-random-bucket-2" 94 | tags = { 95 | Secure = "probably" 96 | } 97 | } 98 | } 99 | } 100 | ``` 101 | -------------------------------------------------------------------------------- /wrappers/rule-group/main.tf: -------------------------------------------------------------------------------- 1 | module "wrapper" { 2 | source = "../../modules/rule-group" 3 | 4 | for_each = var.items 5 | 6 | attach_resource_policy = try(each.value.attach_resource_policy, var.defaults.attach_resource_policy, false) 7 | capacity = try(each.value.capacity, var.defaults.capacity, 100) 8 | create = try(each.value.create, var.defaults.create, true) 9 | create_resource_policy = try(each.value.create_resource_policy, var.defaults.create_resource_policy, false) 10 | description = try(each.value.description, var.defaults.description, null) 11 | encryption_configuration = try(each.value.encryption_configuration, var.defaults.encryption_configuration, {}) 12 | name = try(each.value.name, var.defaults.name, "") 13 | ram_resource_associations = try(each.value.ram_resource_associations, var.defaults.ram_resource_associations, {}) 14 | resource_policy = try(each.value.resource_policy, var.defaults.resource_policy, "") 15 | resource_policy_actions = try(each.value.resource_policy_actions, var.defaults.resource_policy_actions, []) 16 | resource_policy_principals = try(each.value.resource_policy_principals, var.defaults.resource_policy_principals, []) 17 | rule_group = try(each.value.rule_group, var.defaults.rule_group, {}) 18 | rules = try(each.value.rules, var.defaults.rules, null) 19 | tags = try(each.value.tags, var.defaults.tags, {}) 20 | type = try(each.value.type, var.defaults.type, "STATELESS") 21 | } 22 | -------------------------------------------------------------------------------- /wrappers/rule-group/outputs.tf: -------------------------------------------------------------------------------- 1 | output "wrapper" { 2 | description = "Map of outputs of a wrapper." 3 | value = module.wrapper 4 | # sensitive = false # No sensitive module output found 5 | } 6 | -------------------------------------------------------------------------------- /wrappers/rule-group/variables.tf: -------------------------------------------------------------------------------- 1 | variable "defaults" { 2 | description = "Map of default values which will be used for each item." 3 | type = any 4 | default = {} 5 | } 6 | 7 | variable "items" { 8 | description = "Maps of items to create a wrapper from. Values are passed through to the module." 9 | type = any 10 | default = {} 11 | } 12 | -------------------------------------------------------------------------------- /wrappers/rule-group/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0" 3 | 4 | required_providers { 5 | aws = { 6 | source = "hashicorp/aws" 7 | version = ">= 5.2" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /wrappers/variables.tf: -------------------------------------------------------------------------------- 1 | variable "defaults" { 2 | description = "Map of default values which will be used for each item." 3 | type = any 4 | default = {} 5 | } 6 | 7 | variable "items" { 8 | description = "Maps of items to create a wrapper from. Values are passed through to the module." 9 | type = any 10 | default = {} 11 | } 12 | -------------------------------------------------------------------------------- /wrappers/versions.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 1.0" 3 | } 4 | --------------------------------------------------------------------------------
"aws:pass"
]