diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 0000000..2509343 --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,17 @@ +version: 2 + +updates: + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + commit-message: + prefix: feat + + - package-ecosystem: "terraform" + directory: "/" + schedule: + interval: "daily" + commit-message: + prefix: feat diff --git a/.github/workflows/branch-name-check.yaml b/.github/workflows/branch-name-check.yaml new file mode 100644 index 0000000..396e83c --- /dev/null +++ b/.github/workflows/branch-name-check.yaml @@ -0,0 +1,14 @@ +name: 'Branch Naming Check' +on: pull_request + +jobs: + branch-naming-rules: + runs-on: ubuntu-latest + steps: + - uses: deepakputhraya/action-branch-name@master + with: + regex: 'DMVP-[0-9]*' # Regex the branch should match. This example enforces grouping + allowed_prefixes: 'DMVP-' # All branches should start with the given prefix + ignore: master,develop # Ignore exactly matching branch names from convention + min_length: 5 # Min length of the branch name + max_length: 30 # Max length of the branch name diff --git a/.github/workflows/checkov.yaml b/.github/workflows/checkov.yaml new file mode 100644 index 0000000..d1f1f8b --- /dev/null +++ b/.github/workflows/checkov.yaml @@ -0,0 +1,26 @@ +name: Checkov +on: + pull_request: + push: + branches: [main, master] +jobs: + terraform-validate: + runs-on: ubuntu-latest + permissions: + actions: write + contents: write + discussions: write + pull-requests: write + security-events: write + id-token: write + strategy: + matrix: + path: + - / + + steps: + - uses: dasmeta/reusable-actions-workflows/checkov@4.2.0 + with: + fetch-depth: 0 + directory: ${{ matrix.path }} + continue-on-error: true diff --git a/.github/workflows/pr-title-checker.yaml b/.github/workflows/pr-title-checker.yaml new file mode 100644 index 0000000..0ad09fb --- /dev/null +++ b/.github/workflows/pr-title-checker.yaml @@ -0,0 +1,16 @@ +name: 'PR Title Checker' +on: + pull_request: + types: [edited, opened, synchronize, reopened] + +jobs: + title-check: + runs-on: ubuntu-latest + steps: + - uses: deepakputhraya/action-pr-title@v1.0.2 + with: + regex: 'DMVP-[0-9]*:' # Regex the title should match. + allowed_prefixes: 'DMVP-' # title should start with the given prefix + prefix_case_sensitive: false # title prefix are case insensitive + min_length: 5 # Min length of the title + max_length: -1 # Max length of the title diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml new file mode 100644 index 0000000..f43ab25 --- /dev/null +++ b/.github/workflows/pre-commit.yaml @@ -0,0 +1,23 @@ +name: Pre-Commit +on: + pull_request: + push: + branches: [main, master] +jobs: + terraform-validate: + runs-on: ubuntu-latest + permissions: + actions: write + contents: write + discussions: write + pull-requests: write + id-token: write + steps: + - name: Pre-Commit + uses: dasmeta/reusable-actions-workflows/pre-commit@4.2.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + path: modules/${{ matrix.path }} + continue-on-error: true diff --git a/.github/workflows/semantic-release.yaml b/.github/workflows/semantic-release.yaml new file mode 100644 index 0000000..d6ce913 --- /dev/null +++ b/.github/workflows/semantic-release.yaml @@ -0,0 +1,22 @@ +name: Semantic-Release +on: [pull_request, push] +jobs: + publish: + runs-on: ubuntu-latest + permissions: + actions: write + contents: write + discussions: write + pull-requests: write + id-token: write + steps: + - uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + - name: Semantic Release + uses: cycjimmy/semantic-release-action@v4 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/terraform-test.yaml b/.github/workflows/terraform-test.yaml new file mode 100644 index 0000000..b498c3e --- /dev/null +++ b/.github/workflows/terraform-test.yaml @@ -0,0 +1,27 @@ +name: Terraform Test +on: + pull_request: + push: + branches: [main, master] +jobs: + terraform-validate: + permissions: + actions: write + contents: write + discussions: write + pull-requests: write + id-token: write + runs-on: ubuntu-latest + strategy: + matrix: + path: + - / + + steps: + - uses: dasmeta/reusable-actions-workflows/terraform-test@4.2.0 + with: + aws-region: ${{ secrets.AWS_REGION}} + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + path: ${{ matrix.path }} + continue-on-error: true diff --git a/.github/workflows/tflint.yaml b/.github/workflows/tflint.yaml new file mode 100644 index 0000000..fc93d7e --- /dev/null +++ b/.github/workflows/tflint.yaml @@ -0,0 +1,30 @@ +name: Tflint +on: + pull_request: + push: + branches: [main, master] + +jobs: + terraform-validate: + permissions: + actions: write + contents: write + discussions: write + pull-requests: write + id-token: write + security-events: write + runs-on: ubuntu-latest + strategy: + matrix: + path: + - / + + steps: + - uses: dasmeta/reusable-actions-workflows/tflint@4.2.0 + with: + aws-region: ${{ secrets.AWS_REGION}} + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + path: ${{ matrix.path }} + repo-token: ${{ secrets.GITHUB_TOKEN }} + continue-on-error: true diff --git a/.github/workflows/tfsec.yaml b/.github/workflows/tfsec.yaml new file mode 100644 index 0000000..3f9ad3b --- /dev/null +++ b/.github/workflows/tfsec.yaml @@ -0,0 +1,20 @@ +name: TFSEC +on: + pull_request: + push: + branches: [main, master] +jobs: + terraform-tfsec: + runs-on: ubuntu-latest + permissions: + actions: write + contents: write + discussions: write + pull-requests: write + id-token: write + security-events: write + steps: + - uses: dasmeta/reusable-actions-workflows/tfsec@4.2.0 + with: + fetch-depth: 0 + continue-on-error: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..1e2bb60 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,28 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.3.0 + hooks: + - id: check-added-large-files + - id: check-merge-conflict + - id: check-vcs-permalinks + - id: end-of-file-fixer + - id: trailing-whitespace + args: [--markdown-linebreak-ext=md] + exclude: CHANGELOG.md + - id: check-yaml + - id: check-merge-conflict + - id: check-case-conflict + - id: mixed-line-ending + args: [--fix=lf] + - id: detect-aws-credentials + args: ['--allow-missing-credentials'] + - id: detect-private-key + - repo: https://github.com/antonbabenko/pre-commit-terraform + rev: v1.64.1 + hooks: + - id: terraform_fmt + - id: terraform_docs + args: + - --hook-config=--path-to-file=README.md + - --hook-config=--add-to-existing-file=true + - --hook-config=--create-file-if-not-exist=true diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..81c4b92 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,5 @@ +module.exports = { + extends: [ + "@commitlint/config-conventional" + ] +} diff --git a/git-conventional-commits.json b/git-conventional-commits.json new file mode 100644 index 0000000..009fca5 --- /dev/null +++ b/git-conventional-commits.json @@ -0,0 +1,41 @@ +{ + "convention" : { + "commitTypes": [ + "feat", + "fix", + "perf", + "refactor", + "style", + "test", + "build", + "ops", + "docs", + "merge", + "chore" + ], + "commitScopes": [], + "releaseTagGlobPattern": "v[0-9]*.[0-9]*.[0-9]*", + "issueRegexPattern": "(^|\\s)#\\d+(\\s|$)" + }, + "changelog" : { + "commitTypes": [ + "feat", + "fix", + "perf", + "merge" + ], + "includeInvalidCommits": true, + "commitScopes": [], + "commitIgnoreRegexPattern": "^WIP ", + "headlines": { + "feat": "Features", + "fix": "Bug Fixes", + "perf": "Performance Improvements", + "merge": "Merged Branches", + "breakingChange": "BREAKING CHANGES" + }, + "commitUrl": "https://github.com/ACCOUNT/REPOSITORY/commit/%commit%", + "commitRangeUrl": "https://github.com/ACCOUNT/REPOSITORY/compare/%from%...%to%?diff=split", + "issueUrl": "https://github.com/ACCOUNT/REPOSITORY/issues/%issue%" + } +} diff --git a/githooks/commit-msg b/githooks/commit-msg new file mode 100644 index 0000000..cd8f9cb --- /dev/null +++ b/githooks/commit-msg @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +# File generated by pre-commit: https://pre-commit.com +# ID: 138fd403232d2ddd5efb44317e38bf03 + +# start templated +INSTALL_PYTHON=/usr/bin/python3 +ARGS=(hook-impl --config=.pre-commit-config.yaml --hook-type=commit-msg) +# end templated + +HERE="$(cd "$(dirname "$0")" && pwd)" +ARGS+=(--hook-dir "$HERE" -- "$@") + +if command -v pre-commit > /dev/null; then + exec pre-commit "${ARGS[@]}" +elif [ -x "$INSTALL_PYTHON" ]; then + exec "$INSTALL_PYTHON" -mpre_commit "${ARGS[@]}" +else + echo '`pre-commit` not found. Did you forget to activate your virtualenv?' 1>&2 + exit 1a +fi \ No newline at end of file diff --git a/githooks/pre-commit b/githooks/pre-commit new file mode 100644 index 0000000..9b3c4dc --- /dev/null +++ b/githooks/pre-commit @@ -0,0 +1,4 @@ +#!/bin/bash + +set -e +pre-commit run --show-diff-on-failure --color=always --all-files \ No newline at end of file diff --git a/iam.tf b/iam.tf new file mode 100644 index 0000000..9285788 --- /dev/null +++ b/iam.tf @@ -0,0 +1,59 @@ +data "aws_iam_policy_document" "backup_kms" { + + statement { + sid = "Enable IAM User Permissions" + actions = ["kms:*"] + resources = ["*"] + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } + + statement { + sid = "Allow Backup role to use the key" + actions = [ + "kms:Decrypt", + "kms:Encrypt", + ] + + principals { + type = "AWS" + identifiers = [ + aws_iam_role.backup.arn + ] + } + } + +} + +data "aws_iam_policy_document" "assume_backup_role" { + statement { + actions = ["sts:AssumeRole"] + effect = "Allow" + principals { + type = "Service" + identifiers = ["backup.amazonaws.com"] + } + } +} + +resource "aws_iam_role" "backup" { + name = local.vault_name + assume_role_policy = data.aws_iam_policy_document.assume_backup_role.json +} + +resource "aws_iam_role_policy_attachment" "main" { + policy_arn = "arn:aws:iam::aws:policy/service-role/AWSBackupServiceRolePolicyForBackup" + role = aws_iam_role.backup.name +} + +resource "aws_iam_role_policy_attachment" "s3_backup" { + role = aws_iam_role.backup.name + policy_arn = "arn:aws:iam::aws:policy/AWSBackupServiceRolePolicyForS3Backup" +} + +resource "aws_iam_role_policy_attachment" "s3_restore" { + role = aws_iam_role.backup.name + policy_arn = "arn:aws:iam::aws:policy/AWSBackupServiceRolePolicyForS3Restore" +} diff --git a/locals.tf b/locals.tf new file mode 100644 index 0000000..1a7329e --- /dev/null +++ b/locals.tf @@ -0,0 +1,3 @@ +locals { + vault_name = "backup-${var.env}" +} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..3c4a33f --- /dev/null +++ b/main.tf @@ -0,0 +1,64 @@ +data "aws_caller_identity" "current" {} + +resource "aws_kms_key" "backup" { + description = "${var.env}: Encrypt backup recovery points" + deletion_window_in_days = 7 + policy = data.aws_iam_policy_document.backup_kms.json + enable_key_rotation = true +} + +resource "aws_kms_alias" "backup" { + name = "alias/aws_backup-${var.env}" + target_key_id = aws_kms_key.backup.arn +} + +resource "aws_backup_vault" "this" { + name = local.vault_name + kms_key_arn = aws_kms_key.backup.arn + + lifecycle { + prevent_destroy = true + } +} + +resource "aws_backup_plan" "daily" { + name = "daily-${var.env}" + + rule { + rule_name = "daily" + target_vault_name = aws_backup_vault.this.name + schedule = var.backup_schedule + enable_continuous_backup = var.enable_continuous_backup + + lifecycle { + delete_after = var.backup_retention_days + } + + recovery_point_tags = { + Environment = var.env + } + } +} + +resource "aws_backup_selection" "tagged_daily" { + name = "daily-tagged-${var.env}" + plan_id = aws_backup_plan.daily.id + + # selection rules + dynamic "selection_tag" { + for_each = var.plan_selection_tag + content { + type = "STRINGEQUALS" + key = selection_tag.value["key"] + value = selection_tag.value["value"] + + } + + } + selection_tag { + type = "STRINGEQUALS" + key = "backup:rule:efs" + value = "daily-${var.env}" + } + iam_role_arn = aws_iam_role.backup.arn +} diff --git a/monitoring.tf b/monitoring.tf new file mode 100644 index 0000000..14acfa2 --- /dev/null +++ b/monitoring.tf @@ -0,0 +1,147 @@ +data "aws_iam_policy_document" "kms" { + # Copy of default KMS policy that lets you manage it + #checkov:skip=CKV_AWS_111: Does not apply here because KMS key policies only apply to the key itself. (https://docs.bridgecrew.io/docs/ensure-iam-policies-do-not-allow-write-access-without-constraint) + #checkov:skip=CKV_AWS_109: Does not apply here because KMS key policies only apply to the key itself. (https://docs.bridgecrew.io/docs/ensure-iam-policies-do-not-allow-permissions-management-resource-exposure-without-constraint) + #checkov:skip=CKV_AWS_356: ignoring asterisk for policies + statement { + sid = "Enable IAM User Permissions" + actions = ["kms:*"] + resources = ["*"] + + principals { + type = "AWS" + identifiers = ["arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"] + } + } + + statement { + sid = "Allow SNS to use the key" + actions = [ + "kms:Decrypt", + "kms:Encrypt", + ] + + resources = [ + "*", + ] + + principals { + type = "Service" + identifiers = ["sns.amazonaws.com"] + } + + } + + statement { + sid = "Allow AWS Backup to use the key" + actions = [ + "kms:Decrypt", + "kms:Encrypt", + ] + + resources = [ + "*", + ] + + principals { + type = "Service" + identifiers = ["backup.amazonaws.com"] + } + + } +} + +data "aws_iam_policy_document" "backup_notifications" { + #checkov:skip=CKV_AWS_356: ignoring asterisk for policies + policy_id = "aws_backup_${var.env}" + + statement { + sid = "aws_backup_${var.env}" + actions = [ + "SNS:Publish", + ] + + effect = "Allow" + + resources = [ + "*", + ] + + principals { + type = "Service" + identifiers = ["backup.amazonaws.com"] + } + } +} + +resource "aws_lambda_permission" "with_sns" { + count = var.alarm_lambda_arn != "" ? 1 : 0 + statement_id = "allow_backup_${var.env}" + action = "lambda:InvokeFunction" + function_name = var.alarm_lambda_arn + principal = "sns.amazonaws.com" + source_arn = module.sns_topic.sns_topic_arn +} + +resource "aws_kms_key" "this" { + description = "KMS key is used to encrypt this sns topic" + deletion_window_in_days = 7 + enable_key_rotation = true + policy = data.aws_iam_policy_document.kms.json +} + +resource "aws_kms_alias" "backup_sns" { + name = "alias/aws_backup-sns-${var.env}" + target_key_id = aws_kms_key.this.arn +} + +module "sns_topic" { + #checkov:skip=CKV_TF_1: https://github.com/bridgecrewio/checkov/issues/5286 + source = "terraform-aws-modules/sns/aws" + version = "~> 3.0" + + + name = "backups_${var.env}" + display_name = "Backups in ${var.env}" + kms_master_key_id = aws_kms_key.this.arn + policy = data.aws_iam_policy_document.backup_notifications.json +} + +resource "aws_sns_topic_subscription" "lambda" { + count = var.alarm_lambda_arn != "" ? 1 : 0 + topic_arn = module.sns_topic.sns_topic_arn + protocol = "lambda" + endpoint = var.alarm_lambda_arn + filter_policy = local.filter_completed_backups +} + +resource "aws_sns_topic_subscription" "email" { + for_each = length(var.alarm_email_addresses) > 0 ? toset(var.alarm_email_addresses) : toset([]) + topic_arn = module.sns_topic.sns_topic_arn + protocol = "email" + endpoint = each.key + filter_policy = local.filter_completed_backups +} + +locals { + filter_completed_backups = <