From c7717a659fc26a20cfa2f27d371116d55246415b Mon Sep 17 00:00:00 2001 From: Tim Ireland Date: Wed, 17 Jul 2024 09:15:25 +0100 Subject: [PATCH 01/18] CCM-5197 (#32) * CCM-5197 added script * CCM-5197 create autolink script * CCM-5197 fixed README --- scripts/config/vale/styles/Vocab/words/accept.txt | 1 + scripts/git-repo/auto-link.md | 11 +++++++++++ scripts/git-repo/auto-link.sh | 9 +++++++++ 3 files changed, 21 insertions(+) create mode 100644 scripts/git-repo/auto-link.md create mode 100644 scripts/git-repo/auto-link.sh diff --git a/scripts/config/vale/styles/Vocab/words/accept.txt b/scripts/config/vale/styles/Vocab/words/accept.txt index dc124c0..43298b2 100644 --- a/scripts/config/vale/styles/Vocab/words/accept.txt +++ b/scripts/config/vale/styles/Vocab/words/accept.txt @@ -24,3 +24,4 @@ drawio rawContent endcapture Cognito +Jira diff --git a/scripts/git-repo/auto-link.md b/scripts/git-repo/auto-link.md new file mode 100644 index 0000000..dfb68a6 --- /dev/null +++ b/scripts/git-repo/auto-link.md @@ -0,0 +1,11 @@ +# GitHub + +## Auto link Protection Rules + +This will create the auto link to Jira. + +```sh +./auto-link.sh $reponame $PAT +``` + +PAT must have `administration:write`. [Create an auto link](https://docs.github.com/en/rest/repos/autolinks?apiVersion=2022-11-28#create-an-autolink-for-a-repository) diff --git a/scripts/git-repo/auto-link.sh b/scripts/git-repo/auto-link.sh new file mode 100644 index 0000000..a827bd0 --- /dev/null +++ b/scripts/git-repo/auto-link.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +curl -L \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer $2" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/NHSDigital/$1/autolinks \ + -d '{"key_prefix":"CCM-","url_template":" https://nhsd-jira.digital.nhs.uk/browse/CCM-","is_alphanumeric":true}' From 06217c280fa6cc33c2200569d10934da91c7f8d8 Mon Sep 17 00:00:00 2001 From: Tim Ireland Date: Thu, 18 Jul 2024 10:30:40 +0100 Subject: [PATCH 02/18] Create scorecard.yml Added workflow for OSS ScoreCard --- .github/workflows/scorecard.yml | 73 +++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 .github/workflows/scorecard.yml diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 0000000..e98f45d --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,73 @@ +# This workflow uses actions that are not certified by GitHub. They are provided +# by a third-party and are governed by separate terms of service, privacy +# policy, and support documentation. + +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection + branch_protection_rule: + # To guarantee Maintained check is occasionally updated. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained + schedule: + - cron: '15 22 * * 5' + push: + branches: [ "main" ] + +# Declare default permissions as read only. +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + # Needed to publish results and get a badge (see publish_results below). + id-token: write + # Uncomment the permissions below if installing in a private repository. + # contents: read + # actions: read + + steps: + - name: "Checkout code" + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + with: + results_file: results.sarif + results_format: sarif + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: + # - you want to enable the Branch-Protection check on a *public* repository, or + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} + + # Public repositories: + # - Publish results to OpenSSF REST API for easy access by consumers + # - Allows the repository to include the Scorecard badge. + # - See https://github.com/ossf/scorecard-action#publishing-results. + # For private repositories: + # - `publish_results` will always be set to `false`, regardless + # of the value entered here. + publish_results: false + + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF + # format to the repository Actions tab. + - name: "Upload artifact" + uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + # Upload the results to GitHub's code scanning dashboard (optional). + # Commenting out will disable upload of results to your repo's Code Scanning dashboard + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2 # v3.24.9 + with: + sarif_file: results.sarif From 2a17795d8b0f2c3e7c8e62600017683c636a9302 Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Fri, 16 Aug 2024 13:14:17 +0100 Subject: [PATCH 03/18] CCM-6245: TFSec Scanning --- .github/actions/setup/action.yaml | 22 ++++++ .github/actions/tfsec/action.yaml | 17 +++++ .github/workflows/stage-1-commit.yaml | 40 ++++++++++ .tool-versions | 1 + .vscode/settings.json | 1 - scripts/config/tfsec.yaml | 1 + scripts/setup/setup.sh | 43 +++++++++++ scripts/terraform/tfsec.sh | 101 ++++++++++++++++++++++++++ 8 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 .github/actions/setup/action.yaml create mode 100644 .github/actions/tfsec/action.yaml create mode 100644 scripts/config/tfsec.yaml create mode 100755 scripts/setup/setup.sh create mode 100755 scripts/terraform/tfsec.sh diff --git a/.github/actions/setup/action.yaml b/.github/actions/setup/action.yaml new file mode 100644 index 0000000..a7e8b3b --- /dev/null +++ b/.github/actions/setup/action.yaml @@ -0,0 +1,22 @@ +name: Make Config Action +description: Install dependencies and execute make config + +runs: + using: composite + steps: + - name: Install dependencies and execute make config + shell: bash + run: |- + echo -n " + ====================================================================\n + ==== Starting setup for ${{ github.job }} ==== @ $(date) \n + ====================================================================\n + " + + scripts/setup/setup.sh + + echo -n " + ====================================================================\n + ==== Setup done ${{ github.job }} ==== @ $(date) \n + ====================================================================\n + " diff --git a/.github/actions/tfsec/action.yaml b/.github/actions/tfsec/action.yaml new file mode 100644 index 0000000..e63b99c --- /dev/null +++ b/.github/actions/tfsec/action.yaml @@ -0,0 +1,17 @@ +name: "TFSec Scan" +description: "Scan HCL using TFSec" +runs: + using: "composite" + steps: + - name: "TFSec Scan - Components" + shell: bash + run: | + for component in $(find infrastructure/terraform/components -mindepth 1 -type d); do + scripts/terraform/tfsec.sh $component + done + - name: "TFSec Scan - Modules" + shell: bash + run: | + for module in $(find infrastructure/terraform/modules -mindepth 1 -type d); do + scripts/terraform/tfsec.sh $module + done diff --git a/.github/workflows/stage-1-commit.yaml b/.github/workflows/stage-1-commit.yaml index a516b78..ca6fd41 100644 --- a/.github/workflows/stage-1-commit.yaml +++ b/.github/workflows/stage-1-commit.yaml @@ -77,15 +77,55 @@ jobs: fetch-depth: 0 # Full history is needed to compare branches - name: "Check English usage" uses: ./.github/actions/check-english-usage + detect-terraform-changes: + name: "Detect Terraform Changes" + runs-on: ubuntu-latest + outputs: + terraform_changed: ${{ steps.check.outputs.terraform_changed }} + steps: + - name: "Checkout code" + uses: actions/checkout@v4 + + - name: "Check for Terraform changes" + id: check + run: | + git fetch origin main || true # Ensure you have the latest main branch + CHANGED_FILES=$(git diff --name-only HEAD origin/main) + echo "Changed files: $CHANGED_FILES" + + if echo "$CHANGED_FILES" | grep -qE '\.tf$'; then + echo "Terraform files have changed." + echo "terraform_changed=true" >> $GITHUB_OUTPUT + else + echo "No Terraform changes detected." + echo "terraform_changed=false" >> $GITHUB_OUTPUT + fi lint-terraform: name: "Lint Terraform" runs-on: ubuntu-latest timeout-minutes: 2 + needs: detect-terraform-changes + if: needs.detect-terraform-changes.outputs.terraform_changed == 'true' steps: - name: "Checkout code" uses: actions/checkout@v4 - name: "Lint Terraform" uses: ./.github/actions/lint-terraform + tfsec: + name: "TFSec Scan" + runs-on: ubuntu-latest + timeout-minutes: 2 + needs: detect-terraform-changes + if: needs.detect-terraform-changes.outputs.terraform_changed == 'true' + steps: + - name: "Checkout code" + uses: actions/checkout@v4 + - name: "Setup ASDF" + uses: asdf-vm/actions/setup@v3 + - name: "Perform Setup" + uses: ./.github/actions/setup + - name: "TFSec Scan" + uses: ./.github/actions/tfsec count-lines-of-code: name: "Count lines of code" runs-on: ubuntu-latest diff --git a/.tool-versions b/.tool-versions index cd5707c..5550ad2 100644 --- a/.tool-versions +++ b/.tool-versions @@ -4,6 +4,7 @@ terraform 1.9.1 pre-commit 3.6.0 nodejs 18.18.2 gitleaks 8.18.4 +tfsec 1.28.10 # ============================================================================== # The section below is reserved for Docker image versions. diff --git a/.vscode/settings.json b/.vscode/settings.json index 5c7b413..f2454a4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,7 +9,6 @@ "**/CVS": true, "**/Thumbs.db": true, ".devcontainer": true, - ".github": true, ".vscode": false } } diff --git a/scripts/config/tfsec.yaml b/scripts/config/tfsec.yaml new file mode 100644 index 0000000..623796b --- /dev/null +++ b/scripts/config/tfsec.yaml @@ -0,0 +1 @@ +minimum_severity: MEDIUM diff --git a/scripts/setup/setup.sh b/scripts/setup/setup.sh new file mode 100755 index 0000000..b459f3b --- /dev/null +++ b/scripts/setup/setup.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# WARNING: Please DO NOT edit this file! It is maintained in the Repository Template (https://github.com/nhs-england-tools/repository-template). Raise a PR instead. + +set -euo pipefail + +# Pre-Install dependencies and run make config on Github Runner. +# +# Usage: +# $ ./setup.sh +# ============================================================================== + +function main() { + + cd "$(git rev-parse --show-toplevel)" + + run-setup +} + +function run-setup() { + + sudo apt install bundler -y + time make config + + check-setup-status +} + +# Check the exit status of tfsec. +function check-setup-status() { + + if [ $? -eq 0 ]; then + echo "Setup completed successfully." + else + echo "Setup was unsuccessful." + exit 1 + fi +} + +# ============================================================================== + +main "$@" + +exit 0 diff --git a/scripts/terraform/tfsec.sh b/scripts/terraform/tfsec.sh new file mode 100755 index 0000000..9dcaf6f --- /dev/null +++ b/scripts/terraform/tfsec.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash + +# WARNING: Please DO NOT edit this file! It is maintained in the Repository Template (https://github.com/nhs-england-tools/repository-template). Raise a PR instead. + +set -euo pipefail + +# TFSec command wrapper. It will run the command natively if TFSec is +# installed, otherwise it will run it in a Docker container. +# Run tfsec for security checks on Terraform code. +# +# Usage: +# $ ./tfsec.sh [directory] +# ============================================================================== + +function main() { + + cd "$(git rev-parse --show-toplevel)" + + local dir_to_scan=${1:-.} + + if command -v tfsec > /dev/null 2>&1 && ! is-arg-true "${FORCE_USE_DOCKER:-false}"; then + # shellcheck disable=SC2154 + run-tfsec-natively "$dir_to_scan" + else + run-tfsec-in-docker "$dir_to_scan" + fi +} + +# Run tfsec on the specified directory. +# Arguments: +# $1 - Directory to scan +function run-tfsec-natively() { + + local dir_to_scan="$1" + + echo "TFSec found locally, running natively" + + echo "Running TFSec on directory: $dir_to_scan" + tfsec \ + --concise-output \ + --force-all-dirs \ + --exclude-downloaded-modules \ + --config-file ../config/tfsec.yaml \ + --format text \ + "$dir_to_scan" + + check-tfsec-status +} + +# Check the exit status of tfsec. +function check-tfsec-status() { + + if [ $? -eq 0 ]; then + echo "TFSec completed successfully." + else + echo "TFSec found issues." + exit 1 + fi +} + +function run-tfsec-in-docker() { + + # shellcheck disable=SC1091 + source ./scripts/docker/docker.lib.sh + local dir_to_scan="$1" + + # shellcheck disable=SC2155 + local image=$(name=aquasec/tfsec docker-get-image-version-and-pull) + # shellcheck disable=SC2086 + echo "TFSec not found locally, running in Docker Container" + echo "Running TFSec on directory: $dir_to_scan" + docker run --rm --platform linux/amd64 \ + --volume "$PWD":/workdir \ + --workdir /workdir \ + "$image" \ + --concise-output \ + --force-all-dirs \ + --exclude-downloaded-modules \ + --config-file ../config/tfsec.yaml \ + --format text \ + "$dir_to_scan" + check-tfsec-status +} +# ============================================================================== + +function is-arg-true() { + + if [[ "$1" =~ ^(true|yes|y|on|1|TRUE|YES|Y|ON)$ ]]; then + return 0 + else + return 1 + fi +} + +# ============================================================================== + +is-arg-true "${VERBOSE:-false}" && set -x + +main "$@" + +exit 0 From 0cb31ac66fa65867393748b41fbcec2a7b9e0e51 Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Wed, 21 Aug 2024 10:51:26 +0100 Subject: [PATCH 04/18] CCM-6245: TFSec Scanning --- scripts/config/tfsec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/config/tfsec.yaml b/scripts/config/tfsec.yaml index 623796b..550203b 100644 --- a/scripts/config/tfsec.yaml +++ b/scripts/config/tfsec.yaml @@ -1 +1,2 @@ +--- minimum_severity: MEDIUM From 995497d09aa10d87e38b1518650f5b85cd7c25e8 Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Wed, 21 Aug 2024 10:54:24 +0100 Subject: [PATCH 05/18] CCM-6245: TFSec Scanning --- .github/workflows/stage-1-commit.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stage-1-commit.yaml b/.github/workflows/stage-1-commit.yaml index ca6fd41..ed14a61 100644 --- a/.github/workflows/stage-1-commit.yaml +++ b/.github/workflows/stage-1-commit.yaml @@ -114,7 +114,7 @@ jobs: tfsec: name: "TFSec Scan" runs-on: ubuntu-latest - timeout-minutes: 2 + timeout-minutes: 5 needs: detect-terraform-changes if: needs.detect-terraform-changes.outputs.terraform_changed == 'true' steps: From c609f52c1b7aa1fc1f3c53ca37d27b6b627bdaa9 Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Wed, 21 Aug 2024 10:57:15 +0100 Subject: [PATCH 06/18] CCM-6245: TFSec Scanning --- scripts/terraform/tfsec.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/terraform/tfsec.sh b/scripts/terraform/tfsec.sh index 9dcaf6f..10cb909 100755 --- a/scripts/terraform/tfsec.sh +++ b/scripts/terraform/tfsec.sh @@ -40,7 +40,7 @@ function run-tfsec-natively() { --concise-output \ --force-all-dirs \ --exclude-downloaded-modules \ - --config-file ../config/tfsec.yaml \ + --config-file scripts/config/tfsec.yaml \ --format text \ "$dir_to_scan" @@ -76,7 +76,7 @@ function run-tfsec-in-docker() { --concise-output \ --force-all-dirs \ --exclude-downloaded-modules \ - --config-file ../config/tfsec.yaml \ + --config-file scripts/config/tfsec.yaml \ --format text \ "$dir_to_scan" check-tfsec-status From ec625a9c8c886d9076854c30a1c4cad5b77135ef Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Wed, 21 Aug 2024 11:05:18 +0100 Subject: [PATCH 07/18] Test: Repo Template Update --- .vscode/settings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index f2454a4..5ad1f2c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,6 +9,7 @@ "**/CVS": true, "**/Thumbs.db": true, ".devcontainer": true, + ".github": false, ".vscode": false } } From 6877be732ade0c48d12d1a7072abaa9698696f81 Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs <115219893+jamesthompson26-nhs@users.noreply.github.com> Date: Wed, 21 Aug 2024 12:13:59 +0100 Subject: [PATCH 08/18] Update scripts/terraform/tfsec.sh Co-authored-by: Aiden Vaines <54067008+aidenvaines-bjss@users.noreply.github.com> --- scripts/terraform/tfsec.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/terraform/tfsec.sh b/scripts/terraform/tfsec.sh index 10cb909..60deb26 100755 --- a/scripts/terraform/tfsec.sh +++ b/scripts/terraform/tfsec.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# WARNING: Please DO NOT edit this file! It is maintained in the Repository Template (https://github.com/nhs-england-tools/repository-template). Raise a PR instead. +# WARNING: Please DO NOT edit this file! It is maintained in the Repository Template (https://github.com/NHSDigital/nhs-notify-repository-template). Raise a PR instead. set -euo pipefail From dd1e33119b1f827ee1659dd8f8872a5d28571e7d Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs <115219893+jamesthompson26-nhs@users.noreply.github.com> Date: Wed, 21 Aug 2024 12:14:05 +0100 Subject: [PATCH 09/18] Update scripts/setup/setup.sh Co-authored-by: Aiden Vaines <54067008+aidenvaines-bjss@users.noreply.github.com> --- scripts/setup/setup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/setup/setup.sh b/scripts/setup/setup.sh index b459f3b..2a008ef 100755 --- a/scripts/setup/setup.sh +++ b/scripts/setup/setup.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# WARNING: Please DO NOT edit this file! It is maintained in the Repository Template (https://github.com/nhs-england-tools/repository-template). Raise a PR instead. +# WARNING: Please DO NOT edit this file! It is maintained in the Repository Template (https://github.com/NHSDigital/nhs-notify-repository-template). Raise a PR instead. set -euo pipefail From 16fdfd4d0d9935c124787acfd31814850c6d57b2 Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Wed, 21 Aug 2024 12:16:56 +0100 Subject: [PATCH 10/18] Test: Repo Template Update --- .github/actions/setup/action.yaml | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/.github/actions/setup/action.yaml b/.github/actions/setup/action.yaml index a7e8b3b..bd57a9a 100644 --- a/.github/actions/setup/action.yaml +++ b/.github/actions/setup/action.yaml @@ -6,17 +6,5 @@ runs: steps: - name: Install dependencies and execute make config shell: bash - run: |- - echo -n " - ====================================================================\n - ==== Starting setup for ${{ github.job }} ==== @ $(date) \n - ====================================================================\n - " - + run: | scripts/setup/setup.sh - - echo -n " - ====================================================================\n - ==== Setup done ${{ github.job }} ==== @ $(date) \n - ====================================================================\n - " From c6ab5db95fa3f3aed12b11ba5e1c4ff8a4d67e95 Mon Sep 17 00:00:00 2001 From: jamesthompson26-nhs Date: Wed, 21 Aug 2024 13:04:49 +0100 Subject: [PATCH 11/18] CCM-6245: TFSec Scanning --- scripts/terraform/tfsec.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/terraform/tfsec.sh b/scripts/terraform/tfsec.sh index 60deb26..7354995 100755 --- a/scripts/terraform/tfsec.sh +++ b/scripts/terraform/tfsec.sh @@ -42,6 +42,7 @@ function run-tfsec-natively() { --exclude-downloaded-modules \ --config-file scripts/config/tfsec.yaml \ --format text \ + --soft-fail \ "$dir_to_scan" check-tfsec-status @@ -78,6 +79,7 @@ function run-tfsec-in-docker() { --exclude-downloaded-modules \ --config-file scripts/config/tfsec.yaml \ --format text \ + --soft-fail \ "$dir_to_scan" check-tfsec-status } From f78188cfbd215177ce693bddddda1795403daf07 Mon Sep 17 00:00:00 2001 From: aidenvaines-bjss Date: Fri, 30 Aug 2024 09:29:12 +0100 Subject: [PATCH 12/18] CCM-6104 consolidating repo changes for AMET structure back to template --- .tool-versions | 11 ++- infrastructure/environments/dev/.gitkeep | 0 infrastructure/terraform/bin/terraform.sh | 19 +++--- .../terraform/bootstrap/.terraform-version | 1 - .../data_iam_policy_document_bucket.tf | 68 ------------------- .../data_iam_policy_document_kms_key_s3.tf | 46 ------------- .../terraform/bootstrap/dynamodb_table.tf | 26 ------- .../terraform/bootstrap/kms_key_s3.tf | 16 ----- infrastructure/terraform/bootstrap/locals.tf | 13 ---- infrastructure/terraform/bootstrap/outputs.tf | 23 ------- .../terraform/bootstrap/provider_aws.tf | 12 ---- .../terraform/bootstrap/s3_bucket.tf | 14 ---- .../s3_bucket_lifecycle_configuration.tf | 26 ------- .../bootstrap/s3_bucket_ownership_controls.tf | 7 -- .../terraform/bootstrap/s3_bucket_policy.tf | 8 --- .../s3_bucket_public_access_block.tf | 8 --- ...et_server_side_encryption_configuration.tf | 12 ---- .../bootstrap/s3_bucket_versioning.tf | 7 -- .../terraform/bootstrap/variables.tf | 37 ---------- .../terraform/bootstrap/versions.tf | 10 --- .../components/acct/.terraform-version | 1 - .../terraform/components/acct/.tool-versions | 1 + .../terraform/components/acct/README | 5 -- .../cloudwatch_log_group_route53_query_log.tf | 37 ++++++++++ .../components/acct/locals_tfscaffold.tf | 11 ++- .../terraform/components/acct/outputs.tf | 24 ++----- .../terraform/components/acct/provider_aws.tf | 22 +++--- .../components/acct/route53_delegation_set.tf | 3 + .../acct/route53_delegation_set_main.tf | 3 - .../components/acct/route53_query_log.tf | 9 +++ .../terraform/components/acct/route53_zone.tf | 5 ++ .../components/acct/route53_zone_subdomain.tf | 7 -- .../terraform/components/acct/variables.tf | 20 +++--- .../terraform/components/acct/versions.tf | 2 +- .../examplecomponent/.tool-versions | 1 + 35 files changed, 108 insertions(+), 407 deletions(-) delete mode 100644 infrastructure/environments/dev/.gitkeep delete mode 100644 infrastructure/terraform/bootstrap/.terraform-version delete mode 100644 infrastructure/terraform/bootstrap/data_iam_policy_document_bucket.tf delete mode 100644 infrastructure/terraform/bootstrap/data_iam_policy_document_kms_key_s3.tf delete mode 100644 infrastructure/terraform/bootstrap/dynamodb_table.tf delete mode 100644 infrastructure/terraform/bootstrap/kms_key_s3.tf delete mode 100644 infrastructure/terraform/bootstrap/locals.tf delete mode 100644 infrastructure/terraform/bootstrap/outputs.tf delete mode 100644 infrastructure/terraform/bootstrap/provider_aws.tf delete mode 100644 infrastructure/terraform/bootstrap/s3_bucket.tf delete mode 100644 infrastructure/terraform/bootstrap/s3_bucket_lifecycle_configuration.tf delete mode 100644 infrastructure/terraform/bootstrap/s3_bucket_ownership_controls.tf delete mode 100644 infrastructure/terraform/bootstrap/s3_bucket_policy.tf delete mode 100644 infrastructure/terraform/bootstrap/s3_bucket_public_access_block.tf delete mode 100644 infrastructure/terraform/bootstrap/s3_bucket_server_side_encryption_configuration.tf delete mode 100644 infrastructure/terraform/bootstrap/s3_bucket_versioning.tf delete mode 100644 infrastructure/terraform/bootstrap/variables.tf delete mode 100644 infrastructure/terraform/bootstrap/versions.tf delete mode 100644 infrastructure/terraform/components/acct/.terraform-version create mode 100644 infrastructure/terraform/components/acct/.tool-versions delete mode 100644 infrastructure/terraform/components/acct/README create mode 100644 infrastructure/terraform/components/acct/cloudwatch_log_group_route53_query_log.tf create mode 100644 infrastructure/terraform/components/acct/route53_delegation_set.tf delete mode 100644 infrastructure/terraform/components/acct/route53_delegation_set_main.tf create mode 100644 infrastructure/terraform/components/acct/route53_query_log.tf create mode 100644 infrastructure/terraform/components/acct/route53_zone.tf delete mode 100644 infrastructure/terraform/components/acct/route53_zone_subdomain.tf create mode 100644 infrastructure/terraform/components/examplecomponent/.tool-versions diff --git a/.tool-versions b/.tool-versions index 5550ad2..e3d0992 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,9 +1,8 @@ -# This file is for you! Please, updated to the versions agreed by your team. - -terraform 1.9.1 -pre-commit 3.6.0 -nodejs 18.18.2 +act 0.2.64 gitleaks 8.18.4 +pre-commit 3.6.0 +terraform 1.9.2 +vale 3.6.0 tfsec 1.28.10 # ============================================================================== @@ -18,7 +17,7 @@ tfsec 1.28.10 # docker/ghcr.io/nhs-england-tools/github-runner-image 20230909-321fd1e-rt@sha256:ce4fd6035dc450a50d3cbafb4986d60e77cb49a71ab60a053bb1b9518139a646 # SEE: https://github.com/nhs-england-tools/github-runner-image/pkgs/container/github-runner-image # docker/hadolint/hadolint 2.12.0-alpine@sha256:7dba9a9f1a0350f6d021fb2f6f88900998a4fb0aaf8e4330aa8c38544f04db42 # SEE: https://hub.docker.com/r/hadolint/hadolint/tags # docker/hashicorp/terraform 1.5.6@sha256:180a7efa983386a27b43657ed610e9deed9e6c3848d54f9ea9b6cb8a5c8c25f5 # SEE: https://hub.docker.com/r/hashicorp/terraform/tags -# docker/jdkato/vale v2.29.7@sha256:5ccfac574231b006284513ac3e4e9f38833989d83f2a68db149932c09de85149 # SEE: https://hub.docker.com/r/jdkato/vale/tags +# docker/jdkato/vale v3.6.0@sha256:0ef22c8d537f079633cfff69fc46f69a2196072f69cab1ab232e8a79a388e425 # SEE: https://hub.docker.com/r/jdkato/vale/tags # docker/koalaman/shellcheck latest@sha256:e40388688bae0fcffdddb7e4dea49b900c18933b452add0930654b2dea3e7d5c # SEE: https://hub.docker.com/r/koalaman/shellcheck/tags # docker/mstruebing/editorconfig-checker 2.7.1@sha256:dd3ca9ea50ef4518efe9be018d669ef9cf937f6bb5cfe2ef84ff2a620b5ddc24 # SEE: https://hub.docker.com/r/mstruebing/editorconfig-checker/tags # docker/sonarsource/sonar-scanner-cli 5.0.1@sha256:494ecc3b5b1ee1625bd377b3905c4284e4f0cc155cff397805a244dee1c7d575 # SEE: https://hub.docker.com/r/sonarsource/sonar-scanner-cli/tags diff --git a/infrastructure/environments/dev/.gitkeep b/infrastructure/environments/dev/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/infrastructure/terraform/bin/terraform.sh b/infrastructure/terraform/bin/terraform.sh index 22143d1..756b4ef 100755 --- a/infrastructure/terraform/bin/terraform.sh +++ b/infrastructure/terraform/bin/terraform.sh @@ -8,7 +8,7 @@ ## # Set Script Version ## -readonly script_ver="1.8.0"; +readonly script_ver="1.8.1"; ## # Standardised failure function @@ -399,13 +399,16 @@ fi; pushd "${component_path}"; readonly component_name=$(basename ${component_path}); -# Check for presence of tfenv (https://github.com/kamatama41/tfenv) -# and a .terraform-version file. If both present, ensure required -# version of terraform for this component is installed automagically. -tfenv_bin="$(which tfenv 2>/dev/null)"; -if [[ -n "${tfenv_bin}" && -x "${tfenv_bin}" && -f .terraform-version ]]; then - ${tfenv_bin} install; -fi; +# install terraform +# verify terraform version matches .tool-versions +echo ${PWD} +tool_version=$(grep "terraform " .tool-versions | cut -d ' ' -f 2) +asdf plugin-add terraform && asdf install terraform "${tool_version}" +current_version=$(terraform --version | head -n 1 | cut -d 'v' -f 2) + +if [ -z "${current_version}" ] || [ "${current_version}" != "${tool_version}" ]; then + error_and_die "Terraform version mismatch. Expected: ${tool_version}, Actual: ${current_version}" +fi # Regardless of bootstrapping or not, we'll be using this string. # If bootstrapping, we will fill it with variables, diff --git a/infrastructure/terraform/bootstrap/.terraform-version b/infrastructure/terraform/bootstrap/.terraform-version deleted file mode 100644 index 80e78df..0000000 --- a/infrastructure/terraform/bootstrap/.terraform-version +++ /dev/null @@ -1 +0,0 @@ -1.3.5 diff --git a/infrastructure/terraform/bootstrap/data_iam_policy_document_bucket.tf b/infrastructure/terraform/bootstrap/data_iam_policy_document_bucket.tf deleted file mode 100644 index dd231f5..0000000 --- a/infrastructure/terraform/bootstrap/data_iam_policy_document_bucket.tf +++ /dev/null @@ -1,68 +0,0 @@ -data "aws_iam_policy_document" "bucket" { - statement { - sid = "DontAllowNonSecureConnection" - effect = "Deny" - - actions = [ - "s3:*", - ] - - resources = [ - aws_s3_bucket.bucket.arn, - "${aws_s3_bucket.bucket.arn}/*", - ] - - principals { - type = "AWS" - - identifiers = [ - "*", - ] - } - - condition { - test = "Bool" - variable = "aws:SecureTransport" - - values = [ - "false", - ] - } - } - - statement { - sid = "AllowManagedAccountsToList" - effect = "Allow" - - actions = [ - "s3:ListBucket", - ] - - resources = [ - aws_s3_bucket.bucket.arn, - ] - - principals { - type = "AWS" - identifiers = local.ro_principals - } - } - - statement { - sid = "AllowManagedAccountsToGet" - effect = "Allow" - - actions = [ - "s3:GetObject", - ] - - resources = [ - "${aws_s3_bucket.bucket.arn}/*", - ] - - principals { - type = "AWS" - identifiers = local.ro_principals - } - } -} diff --git a/infrastructure/terraform/bootstrap/data_iam_policy_document_kms_key_s3.tf b/infrastructure/terraform/bootstrap/data_iam_policy_document_kms_key_s3.tf deleted file mode 100644 index 9741a08..0000000 --- a/infrastructure/terraform/bootstrap/data_iam_policy_document_kms_key_s3.tf +++ /dev/null @@ -1,46 +0,0 @@ -data "aws_iam_policy_document" "kms_key_s3" { - statement { - sid = "AllowLocalIAMAdministration" - effect = "Allow" - - actions = [ - "*", - ] - - resources = [ - "*", - ] - - principals { - type = "AWS" - identifiers = [ - "arn:aws:iam::${var.aws_account_id}:root", - ] - } - } - - statement { - sid = "AllowManagedAccountsToUse" - effect = "Allow" - - actions = [ - "kms:Decrypt", - "kms:DescribeKey", - "kms:Encrypt", - "kms:GenerateDataKey", - "kms:GenerateDataKeyPair", - "kms:GenerateDataKeyPairWithoutPlaintext", - "kms:GenerateDataKeyWithoutPlaintext", - "kms:ReEncrypt", - ] - - resources = [ - "*", - ] - - principals { - type = "AWS" - identifiers = local.ro_principals - } - } -} diff --git a/infrastructure/terraform/bootstrap/dynamodb_table.tf b/infrastructure/terraform/bootstrap/dynamodb_table.tf deleted file mode 100644 index a5510f8..0000000 --- a/infrastructure/terraform/bootstrap/dynamodb_table.tf +++ /dev/null @@ -1,26 +0,0 @@ -resource "aws_dynamodb_table" "tfscaffold" { - name = var.bucket_name - hash_key = "LockID" - billing_mode = "PAY_PER_REQUEST" - - attribute { - name = "LockID" - type = "S" - } - - point_in_time_recovery { - enabled = true - } - - server_side_encryption { - enabled = true - kms_key_arn = aws_kms_key.s3.arn - } - - tags = merge( - local.default_tags, - { - Name = var.bucket_name - }, - ) -} diff --git a/infrastructure/terraform/bootstrap/kms_key_s3.tf b/infrastructure/terraform/bootstrap/kms_key_s3.tf deleted file mode 100644 index d8a9ff4..0000000 --- a/infrastructure/terraform/bootstrap/kms_key_s3.tf +++ /dev/null @@ -1,16 +0,0 @@ -resource "aws_kms_key" "s3" { - description = "tfscaffold Bootstrap S3 Bucket" - deletion_window_in_days = 10 - enable_key_rotation = true - - policy = data.aws_iam_policy_document.kms_key_s3.json - - # This does not use default tag map merging because bootstrapping is special - # You should use default tag map merging elsewhere - tags = merge( - local.default_tags, - { - Name = "tfscaffold Bootstrap S3 Bucket" - } - ) -} diff --git a/infrastructure/terraform/bootstrap/locals.tf b/infrastructure/terraform/bootstrap/locals.tf deleted file mode 100644 index 1449f88..0000000 --- a/infrastructure/terraform/bootstrap/locals.tf +++ /dev/null @@ -1,13 +0,0 @@ -locals { - ro_principals = compact(distinct(flatten([ - var.tfscaffold_ro_principals, - "arn:aws:iam::${var.aws_account_id}:root", - ]))) - - default_tags = { - "tfscaffold:Environment" = var.environment - "tfscaffold:Project" = var.project - "tfscaffold:Component" = var.component - "tfscaffold:Account" = var.aws_account_id - } -} diff --git a/infrastructure/terraform/bootstrap/outputs.tf b/infrastructure/terraform/bootstrap/outputs.tf deleted file mode 100644 index 05b4902..0000000 --- a/infrastructure/terraform/bootstrap/outputs.tf +++ /dev/null @@ -1,23 +0,0 @@ -output "bucket_name" { - value = aws_s3_bucket.bucket.id -} - -output "bucket_policy" { - value = data.aws_iam_policy_document.bucket.json -} - -output "bucket_arn" { - value = aws_s3_bucket.bucket.arn -} - -output "kms_key_arn" { - value = aws_kms_key.s3.arn -} - -output "kms_key_id" { - value = aws_kms_key.s3.id -} - -output "kms_key_policy" { - value = data.aws_iam_policy_document.kms_key_s3.json -} diff --git a/infrastructure/terraform/bootstrap/provider_aws.tf b/infrastructure/terraform/bootstrap/provider_aws.tf deleted file mode 100644 index 02a8858..0000000 --- a/infrastructure/terraform/bootstrap/provider_aws.tf +++ /dev/null @@ -1,12 +0,0 @@ -# The default AWS provider in the default region -provider "aws" { - region = var.region - - # For no reason other than redundant safety - # we only allow the use of the AWS Account - # specified in the environment variables. - # This helps to prevent accidents. - allowed_account_ids = [ - var.aws_account_id, - ] -} diff --git a/infrastructure/terraform/bootstrap/s3_bucket.tf b/infrastructure/terraform/bootstrap/s3_bucket.tf deleted file mode 100644 index 5d5e092..0000000 --- a/infrastructure/terraform/bootstrap/s3_bucket.tf +++ /dev/null @@ -1,14 +0,0 @@ -resource "aws_s3_bucket" "bucket" { - bucket = var.bucket_name - - force_destroy = false - - # This does not use default tag map merging because bootstrapping is special - # You should use default tag map merging elsewhere - tags = merge( - local.default_tags, - { - Name = "Terraform Scaffold State File Bucket for account ${var.aws_account_id} in region ${var.region}" - } - ) -} diff --git a/infrastructure/terraform/bootstrap/s3_bucket_lifecycle_configuration.tf b/infrastructure/terraform/bootstrap/s3_bucket_lifecycle_configuration.tf deleted file mode 100644 index 4e173b6..0000000 --- a/infrastructure/terraform/bootstrap/s3_bucket_lifecycle_configuration.tf +++ /dev/null @@ -1,26 +0,0 @@ -resource "aws_s3_bucket_lifecycle_configuration" "bucket" { - bucket = aws_s3_bucket.bucket.id - - rule { - id = "bootstrap" - status = "Enabled" - - filter { - prefix = "" - } - - noncurrent_version_transition { - noncurrent_days = "30" - storage_class = "STANDARD_IA" - } - - noncurrent_version_transition { - noncurrent_days = "60" - storage_class = "GLACIER" - } - - noncurrent_version_expiration { - noncurrent_days = "90" - } - } -} diff --git a/infrastructure/terraform/bootstrap/s3_bucket_ownership_controls.tf b/infrastructure/terraform/bootstrap/s3_bucket_ownership_controls.tf deleted file mode 100644 index fc4a359..0000000 --- a/infrastructure/terraform/bootstrap/s3_bucket_ownership_controls.tf +++ /dev/null @@ -1,7 +0,0 @@ -resource "aws_s3_bucket_ownership_controls" "bucket" { - bucket = aws_s3_bucket.bucket.id - - rule { - object_ownership = "BucketOwnerEnforced" - } -} diff --git a/infrastructure/terraform/bootstrap/s3_bucket_policy.tf b/infrastructure/terraform/bootstrap/s3_bucket_policy.tf deleted file mode 100644 index d12922a..0000000 --- a/infrastructure/terraform/bootstrap/s3_bucket_policy.tf +++ /dev/null @@ -1,8 +0,0 @@ -resource "aws_s3_bucket_policy" "bucket" { - bucket = aws_s3_bucket.bucket.id - policy = data.aws_iam_policy_document.bucket.json - - depends_on = [ - aws_s3_bucket_public_access_block.bucket, - ] -} diff --git a/infrastructure/terraform/bootstrap/s3_bucket_public_access_block.tf b/infrastructure/terraform/bootstrap/s3_bucket_public_access_block.tf deleted file mode 100644 index d134b31..0000000 --- a/infrastructure/terraform/bootstrap/s3_bucket_public_access_block.tf +++ /dev/null @@ -1,8 +0,0 @@ -resource "aws_s3_bucket_public_access_block" "bucket" { - bucket = aws_s3_bucket.bucket.id - - block_public_acls = true - block_public_policy = true - ignore_public_acls = true - restrict_public_buckets = true -} diff --git a/infrastructure/terraform/bootstrap/s3_bucket_server_side_encryption_configuration.tf b/infrastructure/terraform/bootstrap/s3_bucket_server_side_encryption_configuration.tf deleted file mode 100644 index 5733d98..0000000 --- a/infrastructure/terraform/bootstrap/s3_bucket_server_side_encryption_configuration.tf +++ /dev/null @@ -1,12 +0,0 @@ -resource "aws_s3_bucket_server_side_encryption_configuration" "bucket" { - bucket = aws_s3_bucket.bucket.id - - rule { - apply_server_side_encryption_by_default { - kms_master_key_id = aws_kms_key.s3.arn - sse_algorithm = "aws:kms" - } - - bucket_key_enabled = true - } -} diff --git a/infrastructure/terraform/bootstrap/s3_bucket_versioning.tf b/infrastructure/terraform/bootstrap/s3_bucket_versioning.tf deleted file mode 100644 index 80c1ab9..0000000 --- a/infrastructure/terraform/bootstrap/s3_bucket_versioning.tf +++ /dev/null @@ -1,7 +0,0 @@ -resource "aws_s3_bucket_versioning" "bucket" { - bucket = aws_s3_bucket.bucket.id - - versioning_configuration { - status = "Enabled" - } -} diff --git a/infrastructure/terraform/bootstrap/variables.tf b/infrastructure/terraform/bootstrap/variables.tf deleted file mode 100644 index d7b1f44..0000000 --- a/infrastructure/terraform/bootstrap/variables.tf +++ /dev/null @@ -1,37 +0,0 @@ -variable "project" { - type = string - description = "The name of the Project we are bootstrapping tfscaffold for" -} - -variable "aws_account_id" { - type = string - description = "The AWS Account ID into which we are bootstrapping tfscaffold" -} - -variable "region" { - type = string - description = "The AWS Region into which we are bootstrapping tfscaffold" -} - -variable "environment" { - type = string - description = "The name of the environment for the bootstrapping process; which is always bootstrap" - default = "bootstrap" -} - -variable "component" { - type = string - description = "The name of the component for the bootstrapping process; which is always bootstrap" - default = "bootstrap" -} - -variable "bucket_name" { - type = string - description = "The name to use for the tfscaffold bucket. This should be provided from tfscaffold shell, not environment or group tfvars" -} - -variable "tfscaffold_ro_principals" { - type = list(string) - description = "A list of Principals permitted to ListBucket and GetObject for Remote State purposes. Normally the root principal of the account" - default = [] -} diff --git a/infrastructure/terraform/bootstrap/versions.tf b/infrastructure/terraform/bootstrap/versions.tf deleted file mode 100644 index 87dc6a9..0000000 --- a/infrastructure/terraform/bootstrap/versions.tf +++ /dev/null @@ -1,10 +0,0 @@ -terraform { - required_providers { - aws = { - source = "hashicorp/aws" - version = "~> 4.61.0" - } - } - - required_version = ">= 0.14.7" -} diff --git a/infrastructure/terraform/components/acct/.terraform-version b/infrastructure/terraform/components/acct/.terraform-version deleted file mode 100644 index 631f790..0000000 --- a/infrastructure/terraform/components/acct/.terraform-version +++ /dev/null @@ -1 +0,0 @@ -latest:^1\.8\. diff --git a/infrastructure/terraform/components/acct/.tool-versions b/infrastructure/terraform/components/acct/.tool-versions new file mode 100644 index 0000000..3874604 --- /dev/null +++ b/infrastructure/terraform/components/acct/.tool-versions @@ -0,0 +1 @@ +terraform 1.9.2 diff --git a/infrastructure/terraform/components/acct/README b/infrastructure/terraform/components/acct/README deleted file mode 100644 index d214887..0000000 --- a/infrastructure/terraform/components/acct/README +++ /dev/null @@ -1,5 +0,0 @@ -README for 'acct' component - Account-level resources - -This component is intended to be run to set up things (such as a DNS subdomain) at the account level, and this should be run for each account belonging to the Notify Domain - i.e. there should be a nonprod and prod environment .tfvars - -Copy the `env_eu-west-2_example.tfvars` file in the `etc` directory and adjust as needed for nonprod and prod for your NHS Notify Domain. diff --git a/infrastructure/terraform/components/acct/cloudwatch_log_group_route53_query_log.tf b/infrastructure/terraform/components/acct/cloudwatch_log_group_route53_query_log.tf new file mode 100644 index 0000000..e30e208 --- /dev/null +++ b/infrastructure/terraform/components/acct/cloudwatch_log_group_route53_query_log.tf @@ -0,0 +1,37 @@ +resource "aws_cloudwatch_log_group" "aws_route53_query_log" { + provider = aws.us-east-1 # Route53 query logging must be in us-east-1 https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_query_log + + name = "/aws/route53/${local.csi}" + retention_in_days = var.log_retention_in_days +} + +resource "aws_cloudwatch_log_resource_policy" "route53_query_logging_policy" { + provider = aws.us-east-1 # Route53 query logging must be in us-east-1 https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route53_query_log + + policy_document = data.aws_iam_policy_document.route53_logs.json + policy_name = "${local.csi}-route53-query-logging-policy" +} + +data "aws_iam_policy_document" "route53_logs" { + statement { + effect = "Allow" + + principals { + type = "Service" + + identifiers = [ + "route53.amazonaws.com" + ] + } + + actions = [ + "logs:CreateLogStream", + "logs:PutLogEvents", + ] + + resources = [ + aws_cloudwatch_log_group.aws_route53_query_log.arn, + "${aws_cloudwatch_log_group.aws_route53_query_log.arn}:*" + ] + } +} diff --git a/infrastructure/terraform/components/acct/locals_tfscaffold.tf b/infrastructure/terraform/components/acct/locals_tfscaffold.tf index e5084cd..b7cf321 100644 --- a/infrastructure/terraform/components/acct/locals_tfscaffold.tf +++ b/infrastructure/terraform/components/acct/locals_tfscaffold.tf @@ -34,12 +34,11 @@ locals { default_tags = merge( var.default_tags, { - Project = var.project - Environment = var.environment - Component = var.component - Group = var.group - NHSNotifyDomain = var.nhs_notify_domain - Name = local.csi + Project = var.project + Environment = var.environment + Component = var.component + Group = var.group + Name = local.csi }, ) } diff --git a/infrastructure/terraform/components/acct/outputs.tf b/infrastructure/terraform/components/acct/outputs.tf index 5bc3418..58f3fef 100644 --- a/infrastructure/terraform/components/acct/outputs.tf +++ b/infrastructure/terraform/components/acct/outputs.tf @@ -1,19 +1,7 @@ -output "aws_account_id" { - value = var.aws_account_id -} - -output "r53_delegation_set_id" { - value = aws_route53_delegation_set.main.id -} - -output "r53_delegation_set_nameservers" { - value = aws_route53_delegation_set.main.name_servers -} - -output "r53_subdomain_name" { - value = var.subdomain_name -} - -output "r53_subdomain_id" { - value = one(aws_route53_zone.subdomain[*].id) +output "dns_zone" { + value = { + id = aws_route53_zone.main.id + name = aws_route53_zone.main.name + nameservers = aws_route53_zone.main.name_servers + } } diff --git a/infrastructure/terraform/components/acct/provider_aws.tf b/infrastructure/terraform/components/acct/provider_aws.tf index a805843..d694811 100644 --- a/infrastructure/terraform/components/acct/provider_aws.tf +++ b/infrastructure/terraform/components/acct/provider_aws.tf @@ -6,13 +6,19 @@ provider "aws" { ] default_tags { - tags = { - Project = var.project - Environment = var.environment - Component = var.component - Group = var.group - NHSNotifyDomain = var.nhs_notify_domain - Name = local.csi - } + tags = local.default_tags } } + +provider "aws" { + alias = "us-east-1" + region = "us-east-1" + + default_tags { + tags = local.default_tags + } + + allowed_account_ids = [ + var.aws_account_id, + ] +} diff --git a/infrastructure/terraform/components/acct/route53_delegation_set.tf b/infrastructure/terraform/components/acct/route53_delegation_set.tf new file mode 100644 index 0000000..d3d0896 --- /dev/null +++ b/infrastructure/terraform/components/acct/route53_delegation_set.tf @@ -0,0 +1,3 @@ +resource "aws_route53_delegation_set" "main" { + reference_name = "unset.${var.root_domain_name}" +} diff --git a/infrastructure/terraform/components/acct/route53_delegation_set_main.tf b/infrastructure/terraform/components/acct/route53_delegation_set_main.tf deleted file mode 100644 index 76ad88e..0000000 --- a/infrastructure/terraform/components/acct/route53_delegation_set_main.tf +++ /dev/null @@ -1,3 +0,0 @@ -resource "aws_route53_delegation_set" "main" { - reference_name = "main" -} diff --git a/infrastructure/terraform/components/acct/route53_query_log.tf b/infrastructure/terraform/components/acct/route53_query_log.tf new file mode 100644 index 0000000..305ebb4 --- /dev/null +++ b/infrastructure/terraform/components/acct/route53_query_log.tf @@ -0,0 +1,9 @@ +resource "aws_route53_query_log" "main" { + zone_id = aws_route53_zone.main.zone_id + + cloudwatch_log_group_arn = aws_cloudwatch_log_group.aws_route53_query_log.arn + + depends_on = [ + aws_cloudwatch_log_resource_policy.route53_query_logging_policy + ] +} diff --git a/infrastructure/terraform/components/acct/route53_zone.tf b/infrastructure/terraform/components/acct/route53_zone.tf new file mode 100644 index 0000000..cfd7be2 --- /dev/null +++ b/infrastructure/terraform/components/acct/route53_zone.tf @@ -0,0 +1,5 @@ +resource "aws_route53_zone" "main" { + name = "unset.${var.root_domain_name}" + + delegation_set_id = aws_route53_delegation_set.main.id +} diff --git a/infrastructure/terraform/components/acct/route53_zone_subdomain.tf b/infrastructure/terraform/components/acct/route53_zone_subdomain.tf deleted file mode 100644 index cc52061..0000000 --- a/infrastructure/terraform/components/acct/route53_zone_subdomain.tf +++ /dev/null @@ -1,7 +0,0 @@ -resource "aws_route53_zone" "subdomain" { - count = var.subdomain_name != "" ? 1 : 0 - - name = var.subdomain_name - - delegation_set_id = aws_route53_delegation_set.main.id -} diff --git a/infrastructure/terraform/components/acct/variables.tf b/infrastructure/terraform/components/acct/variables.tf index f625501..14cf64d 100644 --- a/infrastructure/terraform/components/acct/variables.tf +++ b/infrastructure/terraform/components/acct/variables.tf @@ -41,24 +41,24 @@ variable "component" { default = "acct" } -variable "nhs_notify_domain" { - type = string - description = "The name of the NHS Notify Domain that this is deploying to" -} - variable "default_tags" { type = map(string) description = "A map of default tags to apply to all taggable resources within the component" default = {} } - ## -# Variables specific to the "acct" component +# Variables specific to the "dnsroot"component ## -variable "subdomain_name" { +variable "log_retention_in_days" { + type = number + description = "The retention period in days for the Cloudwatch Logs events to be retained, default of 0 is indefinite" + default = 0 +} + +variable "root_domain_name" { type = string - description = "The subdomain name to create a Route53 zone for" - default = "" + description = "The service's root DNS root nameespace, like nonprod.nhsnotify.national.nhs.uk" + default = "nonprod.nhsnotify.national.nhs.uk" } diff --git a/infrastructure/terraform/components/acct/versions.tf b/infrastructure/terraform/components/acct/versions.tf index ee15bad..5fba18d 100644 --- a/infrastructure/terraform/components/acct/versions.tf +++ b/infrastructure/terraform/components/acct/versions.tf @@ -6,5 +6,5 @@ terraform { } } - required_version = "~> 1.8.4" + required_version = ">= 1.9.0" } diff --git a/infrastructure/terraform/components/examplecomponent/.tool-versions b/infrastructure/terraform/components/examplecomponent/.tool-versions new file mode 100644 index 0000000..3874604 --- /dev/null +++ b/infrastructure/terraform/components/examplecomponent/.tool-versions @@ -0,0 +1 @@ +terraform 1.9.2 From b2f48dd18052940d56fd332a3f642075364d0f4c Mon Sep 17 00:00:00 2001 From: aidenvaines-bjss Date: Fri, 30 Aug 2024 09:44:44 +0100 Subject: [PATCH 13/18] CCM-6104 consolidating repo changes for AMET structure back to template --- .../vocabularies}/words/accept.txt | 30 +++++++++---------- .../vocabularies}/words/reject.txt | 0 2 files changed, 15 insertions(+), 15 deletions(-) rename scripts/config/vale/styles/{Vocab => config/vocabularies}/words/accept.txt (100%) rename scripts/config/vale/styles/{Vocab => config/vocabularies}/words/reject.txt (100%) diff --git a/scripts/config/vale/styles/Vocab/words/accept.txt b/scripts/config/vale/styles/config/vocabularies/words/accept.txt similarity index 100% rename from scripts/config/vale/styles/Vocab/words/accept.txt rename to scripts/config/vale/styles/config/vocabularies/words/accept.txt index 43298b2..3b07d50 100644 --- a/scripts/config/vale/styles/Vocab/words/accept.txt +++ b/scripts/config/vale/styles/config/vocabularies/words/accept.txt @@ -1,27 +1,27 @@ +[A-Z]+s Bitwarden +bot +Cognito Cyber Dependabot +draw.io +drawio +endcapture +endfor +endraw +GitHub Gitleaks Grype +idempotence +Jira OAuth Octokit +onboarding Podman Python +rawContent +sed Syft Terraform -Trufflehog -bot -idempotence -onboarding -sed toolchain -[A-Z]+s -GitHub -endraw -draw.io -endfor -drawio -rawContent -endcapture -Cognito -Jira +Trufflehog diff --git a/scripts/config/vale/styles/Vocab/words/reject.txt b/scripts/config/vale/styles/config/vocabularies/words/reject.txt similarity index 100% rename from scripts/config/vale/styles/Vocab/words/reject.txt rename to scripts/config/vale/styles/config/vocabularies/words/reject.txt From 8c34b83a29eb5bab664361f2e426eec14ee9989a Mon Sep 17 00:00:00 2001 From: aidenvaines-bjss Date: Fri, 30 Aug 2024 09:55:59 +0100 Subject: [PATCH 14/18] CCM-6104 consolidating repo changes for AMET structure back to template --- scripts/terraform/terraform.lib.sh | 6 ++++- scripts/terraform/terraform.mk | 39 ++++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/scripts/terraform/terraform.lib.sh b/scripts/terraform/terraform.lib.sh index 7793b9b..d94213e 100644 --- a/scripts/terraform/terraform.lib.sh +++ b/scripts/terraform/terraform.lib.sh @@ -53,8 +53,12 @@ function terraform-destroy() { # dir=[path to a directory where the command will be executed, relative to the project's top-level directory, default is '.'] # opts=[options to pass to the Terraform fmt command, default is '-recursive'] function terraform-fmt() { + for d in "${PWD}infrastructure/"*; do + if [ -d "$d" ]; then + terraform fmt --recursive "${d}" + fi + done - _terraform fmt -recursive # 'dir' and 'opts' are passed to the function as environment variables, if set } # Validate Terraform code. diff --git a/scripts/terraform/terraform.mk b/scripts/terraform/terraform.mk index 111acda..4a2783a 100644 --- a/scripts/terraform/terraform.mk +++ b/scripts/terraform/terraform.mk @@ -4,11 +4,6 @@ # Custom implementation - implementation of a make target should not exceed 5 lines of effective code. # In most cases there should be no need to modify the existing make targets. -TF_ENV ?= dev -STACK ?= ${stack} -TERRAFORM_STACK ?= $(or ${STACK}, infrastructure/environments/${TF_ENV}) -dir ?= ${TERRAFORM_STACK} - terraform-init: # Initialise Terraform - optional: terraform_dir|dir=[path to a directory where the command will be executed, relative to the project's top-level directory, default is one of the module variables or the example directory, if not set], terraform_opts|opts=[options to pass to the Terraform init command, default is none/empty] @Development make _terraform cmd="init" \ dir=$(or ${terraform_dir}, ${dir}) \ @@ -46,9 +41,11 @@ clean:: # Remove Terraform files (terraform) - optional: terraform_dir|dir=[path opts=$(or ${terraform_opts}, ${opts}) _terraform: # Terraform command wrapper - mandatory: cmd=[command to execute]; optional: dir=[path to a directory where the command will be executed, relative to the project's top-level directory, default is one of the module variables or the example directory, if not set], opts=[options to pass to the Terraform command, default is none/empty] + # 'TERRAFORM_STACK' is passed to the functions as environment variable + TERRAFORM_STACK=$(or ${TERRAFORM_STACK}, $(or ${terraform_stack}, $(or ${STACK}, ${stack}))) dir=$(or ${dir}, ${TERRAFORM_STACK}) - . scripts/terraform/terraform.lib.sh && \ - terraform-${cmd} # 'dir' and 'opts' are accessible by the function as environment variables, if set + . "scripts/terraform/terraform.lib.sh"; \ + terraform-${cmd} # 'dir' and 'opts' are accessible by the function as environment variables, if set # ============================================================================== # Quality checks - please DO NOT edit this section! @@ -58,6 +55,31 @@ terraform-shellscript-lint: # Lint all Terraform module shell scripts @Quality file=$${file} scripts/shellscript-linter.sh done +terraform-sec: # TFSEC check against Terraform files - optional: terraform_dir|dir=[path to a directory where the command will be executed, relative to the project's top-level directory, default is one of the module variables or the example directory, if not set], terraform_opts|opts=[options to pass to the Terraform fmt command, default is '-recursive'] @Quality + tfsec infrastructure/terraform \ + --force-all-dirs \ + --exclude-downloaded-modules \ + --tfvars-file infrastructure/terraform/etc/global.tfvars \ + --tfvars-file infrastructure/terraform/etc/env_eu-west-2_main.tfvars \ + --config-file scripts/config/tfsec.yml + +# ============================================================================== +# Module tests and examples - please DO NOT edit this section! + +terraform-example-provision-aws-infrastructure: # Provision example of AWS infrastructure @ExamplesAndTests + make terraform-init + make terraform-plan opts="-out=terraform.tfplan" + make terraform-apply opts="-auto-approve terraform.tfplan" + +terraform-example-destroy-aws-infrastructure: # Destroy example of AWS infrastructure @ExamplesAndTests + make terraform-destroy opts="-auto-approve" + +terraform-example-clean: # Remove Terraform example files @ExamplesAndTests + dir=$(or ${dir}, ${TERRAFORM_STACK}) + . "scripts/terraform/terraform.lib.sh"; \ + terraform-clean + rm -f ${TERRAFORM_STACK}/.terraform.lock.hcl + # ============================================================================== # Configuration - please DO NOT edit this section! @@ -71,6 +93,9 @@ ${VERBOSE}.SILENT: \ clean \ terraform-apply \ terraform-destroy \ + terraform-example-clean \ + terraform-example-destroy-aws-infrastructure \ + terraform-example-provision-aws-infrastructure \ terraform-fmt \ terraform-init \ terraform-install \ From a3204f284ef8c48857b971ef481909e628bdfbd8 Mon Sep 17 00:00:00 2001 From: aidenvaines-bjss Date: Mon, 2 Sep 2024 15:10:19 +0100 Subject: [PATCH 15/18] Adding github workflow to combine dependabot PRs --- .../manual-combine-dependabot-prs.yaml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/manual-combine-dependabot-prs.yaml diff --git a/.github/workflows/manual-combine-dependabot-prs.yaml b/.github/workflows/manual-combine-dependabot-prs.yaml new file mode 100644 index 0000000..c527a23 --- /dev/null +++ b/.github/workflows/manual-combine-dependabot-prs.yaml @@ -0,0 +1,24 @@ +name: Combine Dependabot PRs + +on: + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + checks: read + +jobs: + combine-prs: + runs-on: ubuntu-latest + + steps: + - name: combine-prs + id: combine-prs + uses: github/combine-prs@v5.1.0 + with: + ci_required: false + labels: dependencies + pr_title: Combined Dependabot PRs + combine_branch_name: dependabotCombined + pr_body_header: Combined Dependabot PRs From 64fc66f3c037604cb0bd0c1c0a7ae9a894a3028a Mon Sep 17 00:00:00 2001 From: Mike Houston Date: Mon, 2 Sep 2024 17:46:50 +0100 Subject: [PATCH 16/18] CCM-5831: Git pre-commit hooks tweaks + Exclude Chrome version number in useragent strings from gitleaks + Sort dictionary files in pre-commit hook + Update version of Vale --- .tool-versions | 3 +- scripts/config/gitleaks.toml | 6 +++ scripts/config/pre-commit.yaml | 7 +++ .../vocabularies}/words/accept.txt | 30 ++++++------ .../vocabularies}/words/reject.txt | 0 scripts/githooks/sort-dictionary.sh | 48 +++++++++++++++++++ 6 files changed, 78 insertions(+), 16 deletions(-) rename scripts/config/vale/styles/{Vocab => config/vocabularies}/words/accept.txt (100%) rename scripts/config/vale/styles/{Vocab => config/vocabularies}/words/reject.txt (100%) create mode 100755 scripts/githooks/sort-dictionary.sh diff --git a/.tool-versions b/.tool-versions index 5550ad2..b5b0815 100644 --- a/.tool-versions +++ b/.tool-versions @@ -4,6 +4,7 @@ terraform 1.9.1 pre-commit 3.6.0 nodejs 18.18.2 gitleaks 8.18.4 +vale 3.6.0 tfsec 1.28.10 # ============================================================================== @@ -18,7 +19,7 @@ tfsec 1.28.10 # docker/ghcr.io/nhs-england-tools/github-runner-image 20230909-321fd1e-rt@sha256:ce4fd6035dc450a50d3cbafb4986d60e77cb49a71ab60a053bb1b9518139a646 # SEE: https://github.com/nhs-england-tools/github-runner-image/pkgs/container/github-runner-image # docker/hadolint/hadolint 2.12.0-alpine@sha256:7dba9a9f1a0350f6d021fb2f6f88900998a4fb0aaf8e4330aa8c38544f04db42 # SEE: https://hub.docker.com/r/hadolint/hadolint/tags # docker/hashicorp/terraform 1.5.6@sha256:180a7efa983386a27b43657ed610e9deed9e6c3848d54f9ea9b6cb8a5c8c25f5 # SEE: https://hub.docker.com/r/hashicorp/terraform/tags -# docker/jdkato/vale v2.29.7@sha256:5ccfac574231b006284513ac3e4e9f38833989d83f2a68db149932c09de85149 # SEE: https://hub.docker.com/r/jdkato/vale/tags +# docker/jdkato/vale v3.6.0@sha256:0ef22c8d537f079633cfff69fc46f69a2196072f69cab1ab232e8a79a388e425 # SEE: https://hub.docker.com/r/jdkato/vale/tags # docker/koalaman/shellcheck latest@sha256:e40388688bae0fcffdddb7e4dea49b900c18933b452add0930654b2dea3e7d5c # SEE: https://hub.docker.com/r/koalaman/shellcheck/tags # docker/mstruebing/editorconfig-checker 2.7.1@sha256:dd3ca9ea50ef4518efe9be018d669ef9cf937f6bb5cfe2ef84ff2a620b5ddc24 # SEE: https://hub.docker.com/r/mstruebing/editorconfig-checker/tags # docker/sonarsource/sonar-scanner-cli 5.0.1@sha256:494ecc3b5b1ee1625bd377b3905c4284e4f0cc155cff397805a244dee1c7d575 # SEE: https://hub.docker.com/r/sonarsource/sonar-scanner-cli/tags diff --git a/scripts/config/gitleaks.toml b/scripts/config/gitleaks.toml index e4b6bc1..188bfdf 100644 --- a/scripts/config/gitleaks.toml +++ b/scripts/config/gitleaks.toml @@ -22,3 +22,9 @@ paths = [ '''yarn.lock''', '''Gemfile.lock''', ] + +# Exclude Chrome version in user agent +regexTarget = "line" +regexes = [ + '''Chrome/[\d.]+''' +] diff --git a/scripts/config/pre-commit.yaml b/scripts/config/pre-commit.yaml index 41dafe7..5a5ba09 100644 --- a/scripts/config/pre-commit.yaml +++ b/scripts/config/pre-commit.yaml @@ -15,6 +15,13 @@ repos: - id: pretty-format-json args: ['--autofix'] # - id: ... + - repo: local + hooks: + - id: sort-dictionary + name: Sort dictionary + entry: ./scripts/githooks/sort-dictionary.sh + language: script + pass_filenames: false - repo: local hooks: - id: scan-secrets diff --git a/scripts/config/vale/styles/Vocab/words/accept.txt b/scripts/config/vale/styles/config/vocabularies/words/accept.txt similarity index 100% rename from scripts/config/vale/styles/Vocab/words/accept.txt rename to scripts/config/vale/styles/config/vocabularies/words/accept.txt index 43298b2..3b07d50 100644 --- a/scripts/config/vale/styles/Vocab/words/accept.txt +++ b/scripts/config/vale/styles/config/vocabularies/words/accept.txt @@ -1,27 +1,27 @@ +[A-Z]+s Bitwarden +bot +Cognito Cyber Dependabot +draw.io +drawio +endcapture +endfor +endraw +GitHub Gitleaks Grype +idempotence +Jira OAuth Octokit +onboarding Podman Python +rawContent +sed Syft Terraform -Trufflehog -bot -idempotence -onboarding -sed toolchain -[A-Z]+s -GitHub -endraw -draw.io -endfor -drawio -rawContent -endcapture -Cognito -Jira +Trufflehog diff --git a/scripts/config/vale/styles/Vocab/words/reject.txt b/scripts/config/vale/styles/config/vocabularies/words/reject.txt similarity index 100% rename from scripts/config/vale/styles/Vocab/words/reject.txt rename to scripts/config/vale/styles/config/vocabularies/words/reject.txt diff --git a/scripts/githooks/sort-dictionary.sh b/scripts/githooks/sort-dictionary.sh new file mode 100755 index 0000000..45a3952 --- /dev/null +++ b/scripts/githooks/sort-dictionary.sh @@ -0,0 +1,48 @@ +#!/bin/bash + +set -euo pipefail + +# Pre-commit git hook to sort the Vale dictionary in a consistent manner to avoid future merge conflicts and aid insertion of new terms +# +# Usage: +# $ [options] ./sort-dictionary.sh +# +# Options: +# +# +# Exit codes: +# 0 - Successfully sorted the dictionary +# non-zero - failed to sort dictionary + +# ============================================================================== + +function main() { + root=scripts/config/vale/styles/config/vocabularies/words + opts="--dictionary-order --ignore-case -s" + sort $opts $root/accept.txt > $root/accept.sorted.txt + sort $opts $root/reject.txt > $root/reject.sorted.txt + + mv $root/accept.sorted.txt $root/accept.txt + mv $root/reject.sorted.txt $root/reject.txt + + git add -uv $root/* +} + +# ============================================================================== + +function is-arg-true() { + + if [[ "$1" =~ ^(true|yes|y|on|1|TRUE|YES|Y|ON)$ ]]; then + return 0 + else + return 1 + fi +} + +# ============================================================================== + +is-arg-true "${VERBOSE:-false}" && set -x + +main "$@" + +exit 0 From 925ec0c61f284a1e55981c68953908257ce880ce Mon Sep 17 00:00:00 2001 From: aidenvaines-bjss Date: Tue, 10 Sep 2024 16:19:27 +0100 Subject: [PATCH 17/18] CCM-6405 Adding github workflow to sync template repo --- .../scheduled-repository-template-sync.yaml | 54 +++++++++ .../config/.repository-template-sync-ignore | 18 +++ scripts/githooks/sync-template-repo.sh | 110 ++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 .github/workflows/scheduled-repository-template-sync.yaml create mode 100644 scripts/config/.repository-template-sync-ignore create mode 100755 scripts/githooks/sync-template-repo.sh diff --git a/.github/workflows/scheduled-repository-template-sync.yaml b/.github/workflows/scheduled-repository-template-sync.yaml new file mode 100644 index 0000000..a227476 --- /dev/null +++ b/.github/workflows/scheduled-repository-template-sync.yaml @@ -0,0 +1,54 @@ +name: Repository Template Sync + +on: + schedule: + - cron: '0 0 1 * *' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + checks: read + +jobs: + update-external-repo: + runs-on: ubuntu-latest + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + + - name: Check out external repository + uses: actions/checkout@v4 + with: + repository: NHSDigital/nhs-notify-repository-template + path: nhs-notify-repository-template + token: ${{ github.token }} + + - name: Run syncronisation script + run: | + ./scripts/githooks/sync-template-repo.sh + + - name: Create Pull Request + if: ${{ !env.ACT }} + uses: peter-evans/create-pull-request@v7.0.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Drift from template + branch: scheduledTemplateRepositorySync + delete-branch: true + title: '[Template Sync] Drift from template-repository remediation' + body: | + # Resultant drift from repository template + + ## Who should respond to this PR? + The team which owns the responsibility for this component repository. You may want to consult other contributors. + + ## How to progress this PR + The repositories guardians should review the contents of the PR and decide how to proceed, you may wish to back-out certain changes or accept them from the upstream `nhsdigital/nhs-notify-repository-template` repository. + + If there are changes you do not wish to see again, it is recommended you add exclusions to `scripts/config/.repository-template-sync-ignore`. + labels: | + template + automation + draft: false diff --git a/scripts/config/.repository-template-sync-ignore b/scripts/config/.repository-template-sync-ignore new file mode 100644 index 0000000..7564f3e --- /dev/null +++ b/scripts/config/.repository-template-sync-ignore @@ -0,0 +1,18 @@ +# Files and folders to ignore when syncing nhs-notify-repository-template back in to this repository +scripts/config/.repository-template-sync-ignore +.github/workflows/ +nhs-notify-repository-template/ + +# Files and Folders in this repository to ignore +.vscode/ +CHANGELOG.md +project.code-workspace +README.md +VERSION + +# Files and Folders in the template repository to disregard +.devcontainer/ +.github/workflows/cicd-*.yaml +*/examples/ +docs/ +infrastructure/terraform/components/ diff --git a/scripts/githooks/sync-template-repo.sh b/scripts/githooks/sync-template-repo.sh new file mode 100755 index 0000000..060aaa4 --- /dev/null +++ b/scripts/githooks/sync-template-repo.sh @@ -0,0 +1,110 @@ +#!/bin/bash + +set -euo pipefail + +# Script to synchronise the nhs-notify-template-repository with this repository +# +# Usage: +# $ [options] ./check-terraform-format.sh +# +# Options: +# new_only=true # Only identify new files from the template-repository +# changes_only=true # Only identify files which have drifted from the template-repository + +# ============================================================================== + +# Command line prameters +new_only=${new_only:-false} +changes_only=${changes_only:-false} + +# Set variables +TEMPLATE_REPO_DIR="nhs-notify-repository-template" +IGNORE_FILE="scripts/config/.repository-template-sync-ignore" + +# Check if the template directory exists +if [ ! -d "${TEMPLATE_REPO_DIR}" ]; then + echo "Template directory ${TEMPLATE_REPO_DIR} not found!" + exit 1 +fi + +# Check if the .template-ignore file exists, create an empty one if not +if [ ! -f "${IGNORE_FILE}" ]; then + echo "# Files and folders to ignore when syncing ${TEMPLATE_REPO_DIR} back in to this repository" > ${IGNORE_FILE} + echo "# Files and Folders in this repository to ignore" >> ${IGNORE_FILE} + echo "# Files and Folders in the template repository to disregard" >> ${IGNORE_FILE} +fi + +# Read the .template-ignore file into an array +while IFS= read -r line || [ -n "$line" ]; do + IGNORED_PATHS+=("$line") +done < "$IGNORE_FILE" + +# Check if a file is ignored. +is_ignored() { + local file=${1} + + # Ignore .git directories and files + if [[ "$file" == *.git/* ]]; then + return 0 + fi + + for ignored in "${IGNORED_PATHS[@]}"; do + if [[ -n "$ignored" && "$file" =~ $ignored ]]; then + return 0 + fi + done + return 1 +} + +# Navigate to the template directory +cd "${TEMPLATE_REPO_DIR}" || exit +FILES_ADDED=() +FILES_WITH_CHANGES=() + +# Loop through all files in the template directory +while IFS= read -r -d '' file; do + relative_path="${file#./}" # Remove leading './' + + # Check if the file is ignored + if is_ignored "$relative_path"; then + echo "Ignoring $relative_path" + continue + fi + + target_path="../$relative_path" + mkdir -p "$(dirname "$target_path")" + + # Copy the file to the root directory if it doesn't exist or is different + if [ ! -f "$target_path" ] && [ "$changes_only" == false ]; then + echo "Copying $relative_path to the repository" + FILES_ADDED+=("${relative_path}") + cp "$file" "$target_path" + + else + # If the file exists, check if it's different + if [ "$new_only" == false ]; then + if ! diff -q "$file" "$target_path" > /dev/null 2>&1; then + echo "Merging changes from $relative_path" + FILES_WITH_CHANGES+=("${relative_path}") + cp "$file" "$target_path" + fi + fi + fi +done < <(find . -type f -print0) + +echo "${#FILES_ADDED[@]}" files added, "${#FILES_WITH_CHANGES[@]}" files with changes detected. + +echo ------------------------------------------ + +if [ "$changes_only" == false ]; then + echo ------------------------------------------ + echo "New files added:" + printf ' - %s\n' "${FILES_ADDED[@]}" +fi + + +if [ "$new_only" == false ]; then + echo ------------------------------------------ + echo "Changed files:" + printf ' - %s\n' "${FILES_WITH_CHANGES[@]}" +fi From a256ef4ad62c45699133bd90ed9682551dc56240 Mon Sep 17 00:00:00 2001 From: aidenvaines-bjss Date: Wed, 11 Sep 2024 08:29:26 +0100 Subject: [PATCH 18/18] CCM-6405 Adding github workflow to sync template repo --- .../scheduled-repository-template-sync.yaml | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .github/workflows/scheduled-repository-template-sync.yaml diff --git a/.github/workflows/scheduled-repository-template-sync.yaml b/.github/workflows/scheduled-repository-template-sync.yaml new file mode 100644 index 0000000..aa688da --- /dev/null +++ b/.github/workflows/scheduled-repository-template-sync.yaml @@ -0,0 +1,55 @@ +name: Repository Template Sync + +on: + schedule: + - cron: '0 0 1 * *' + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + checks: read + +jobs: + update-external-repo: + runs-on: ubuntu-latest + + steps: + - name: Check out the repository + uses: actions/checkout@v4 + + - name: Check out external repository + uses: actions/checkout@v4 + with: + repository: NHSDigital/nhs-notify-repository-template + path: nhs-notify-repository-template + token: ${{ github.token }} + + - name: Run syncronisation script + run: | + ./scripts/githooks/sync-template-repo.sh + rm -Rf ./nhs-notify-repository-template + + - name: Create Pull Request + if: ${{ !env.ACT }} + uses: peter-evans/create-pull-request@v7.0.1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Drift from template + branch: scheduledTemplateRepositorySync + delete-branch: true + title: '[Template Sync] Drift from template-repository remediation' + body: | + # Resultant drift from repository template + + ## Who should respond to this PR? + The team which owns the responsibility for this component repository. You may want to consult other contributors. + + ## How to progress this PR + The repositories guardians should review the contents of the PR and decide how to proceed, you may wish to back-out certain changes or accept them from the upstream `nhsdigital/nhs-notify-repository-template` repository. + + If there are changes you do not wish to see again, it is recommended you add exclusions to `scripts/config/.repository-template-sync-ignore`. + labels: | + template + automation + draft: false