From 038116f78c4d54d0d18291818590296eb84b432c Mon Sep 17 00:00:00 2001 From: SteveLinden Date: Wed, 12 Jun 2024 15:49:17 +0100 Subject: [PATCH 1/2] Deleting tariff ID --- .../reusable_terraform_plan_apply.yml | 5 +- .github/workflows/tariff.yml | 66 ------- terraform/environments/tariff/README.md | 76 -------- .../tariff/application_variables.json | 16 -- terraform/environments/tariff/data.tf | 1 - terraform/environments/tariff/locals.tf | 1 - .../tariff/networking.auto.tfvars.json | 9 - .../environments/tariff/platform_backend.tf | 14 -- .../tariff/platform_base_variables.tf | 11 -- .../environments/tariff/platform_data.tf | 173 ------------------ .../environments/tariff/platform_locals.tf | 38 ---- .../environments/tariff/platform_providers.tf | 58 ------ .../environments/tariff/platform_secrets.tf | 17 -- .../environments/tariff/platform_versions.tf | 13 -- terraform/environments/tariff/s3.tf | 53 ------ terraform/environments/tariff/secrets.tf | 1 - 16 files changed, 4 insertions(+), 548 deletions(-) delete mode 100644 .github/workflows/tariff.yml delete mode 100644 terraform/environments/tariff/README.md delete mode 100644 terraform/environments/tariff/application_variables.json delete mode 100644 terraform/environments/tariff/data.tf delete mode 100644 terraform/environments/tariff/locals.tf delete mode 100644 terraform/environments/tariff/networking.auto.tfvars.json delete mode 100644 terraform/environments/tariff/platform_backend.tf delete mode 100644 terraform/environments/tariff/platform_base_variables.tf delete mode 100644 terraform/environments/tariff/platform_data.tf delete mode 100644 terraform/environments/tariff/platform_locals.tf delete mode 100644 terraform/environments/tariff/platform_providers.tf delete mode 100644 terraform/environments/tariff/platform_secrets.tf delete mode 100644 terraform/environments/tariff/platform_versions.tf delete mode 100644 terraform/environments/tariff/s3.tf delete mode 100644 terraform/environments/tariff/secrets.tf diff --git a/.github/workflows/reusable_terraform_plan_apply.yml b/.github/workflows/reusable_terraform_plan_apply.yml index 588e698ad23..0fdf3917f76 100644 --- a/.github/workflows/reusable_terraform_plan_apply.yml +++ b/.github/workflows/reusable_terraform_plan_apply.yml @@ -230,7 +230,8 @@ jobs: core.notice('Pull request approved by a member of @ministryofjustice/modernisation-platform'); } else { - core.setFailed('Terraform plan evaluation detected changes to resources that require approval from a member of @ministryofjustice/modernisation-platform - please contact #ask-modernisation-platform for assistance'); + core.setFailed('Terraform plan evaluation detected changes to resources that require approval from a member of @ministryofjustice/modernisation-platform - please contact #ask-modernisation-platform for assistance' + # NEW code here); await github.rest.pulls.createReview({ owner: context.repo.owner, @@ -238,6 +239,7 @@ jobs: pull_number: context.payload.pull_request.number, event: 'REQUEST_CHANGES', body: 'Terraform plan evaluation detected changes to resources that require approval from @ministryofjustice/modernsation-platform - please contact #ask-modernisation-platform for assistance' + # NEW code here }); } @@ -256,6 +258,7 @@ jobs: repo: repo, issue_number: context.payload.pull_request.number, body: `@${context.actor} Terraform plan evaluation detected changes to resources that require approval from a member of @ministryofjustice/modernisation-platform - please contact #ask-modernisation-platform for assistance` + # NEW code here }); apply: diff --git a/.github/workflows/tariff.yml b/.github/workflows/tariff.yml deleted file mode 100644 index 09b2b9f768b..00000000000 --- a/.github/workflows/tariff.yml +++ /dev/null @@ -1,66 +0,0 @@ ---- -name: tariff -on: - push: - branches: - - main - paths: - - 'terraform/environments/tariff/**' - - '.github/workflows/tariff.yml' - - pull_request: - branches: - - main - types: [opened, edited, reopened, synchronize] - paths: - - 'terraform/environments/tariff/**' - - '.github/workflows/tariff.yml' - - workflow_dispatch: - inputs: - action: - description: 'Set either [deploy|destroy].' - default: 'deploy' - required: true - type: string - options: - - deploy - - destroy - -permissions: - id-token: write # This is required for requesting the JWT - contents: read # This is required for actions/checkout - -jobs: - strategy: - uses: ./.github/workflows/reusable_terraform_strategy.yml - if: inputs.action != 'destroy' - with: - application: "${{ github.workflow }}" - - terraform: - needs: strategy - if: inputs.action != 'destroy' - strategy: - fail-fast: false - matrix: ${{ fromJson(needs.strategy.outputs.matrix) }} - uses: ./.github/workflows/reusable_terraform_plan_apply.yml - with: - application: "${{ github.workflow }}" - environment: "${{ matrix.target }}" - action: "${{ matrix.action }}" - secrets: - modernisation_platform_environments: "${{ secrets.MODERNISATION_PLATFORM_ENVIRONMENTS }}" - pipeline_github_token: "${{ secrets.MODERNISATION_PLATFORM_CI_USER_ENVIRONMENTS_REPO_PAT }}" - - destroy-development: - if: inputs.action == 'destroy' - uses: ./.github/workflows/reusable_terraform_plan_apply.yml - with: - application: "${{ github.workflow }}" - environment: "development" - action: "plan_apply" - plan_apply_tfargs: "-destroy" - secrets: - modernisation_platform_environments: "${{ secrets.MODERNISATION_PLATFORM_ENVIRONMENTS }}" - pipeline_github_token: "${{ secrets.MODERNISATION_PLATFORM_CI_USER_ENVIRONMENTS_REPO_PAT }}" diff --git a/terraform/environments/tariff/README.md b/terraform/environments/tariff/README.md deleted file mode 100644 index 9aa2658704c..00000000000 --- a/terraform/environments/tariff/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# Service Runbook - - - -_If you have any questions surrounding this page please post in the `#team-name` channel._ - -## Mandatory Information - -### **Last review date:** - - - -### **Description:** - - - -### **Service URLs:** - - - -### **Incident response hours:** - - - -### **Incident contact details:** - - - -### **Service team contact:** - - - -### **Hosting environment:** - -Modernisation Platform - - - -## Optional - -### **Other URLs:** - - - -### **Expected speed and frequency of releases:** - - - -### **Automatic alerts:** - - - -### **Impact of an outage:** - - - -### **Out of hours response types:** - - - -### **Consumers of this service:** - - - -### **Services consumed by this:** - - - -### **Restrictions on access:** - - - -### **How to resolve specific issues:** - - diff --git a/terraform/environments/tariff/application_variables.json b/terraform/environments/tariff/application_variables.json deleted file mode 100644 index 6b52bfe9b30..00000000000 --- a/terraform/environments/tariff/application_variables.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "accounts": { - "development": { - "example_var": "dev-data" - }, - "test": { - "example_var": "test-data" - }, - "preproduction": { - "example_var": "preproduction-data" - }, - "production": { - "example_var": "production-data" - } - } -} diff --git a/terraform/environments/tariff/data.tf b/terraform/environments/tariff/data.tf deleted file mode 100644 index 96a2521d17e..00000000000 --- a/terraform/environments/tariff/data.tf +++ /dev/null @@ -1 +0,0 @@ -#### This file can be used to store data specific to the member account #### diff --git a/terraform/environments/tariff/locals.tf b/terraform/environments/tariff/locals.tf deleted file mode 100644 index a7454414911..00000000000 --- a/terraform/environments/tariff/locals.tf +++ /dev/null @@ -1 +0,0 @@ -#### This file can be used to store locals specific to the member account #### diff --git a/terraform/environments/tariff/networking.auto.tfvars.json b/terraform/environments/tariff/networking.auto.tfvars.json deleted file mode 100644 index 8b2e2607ecc..00000000000 --- a/terraform/environments/tariff/networking.auto.tfvars.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "networking": [ - { - "business-unit": "cica", - "set": "general", - "application": "tariff" - } - ] -} diff --git a/terraform/environments/tariff/platform_backend.tf b/terraform/environments/tariff/platform_backend.tf deleted file mode 100644 index 4fcf4f924cc..00000000000 --- a/terraform/environments/tariff/platform_backend.tf +++ /dev/null @@ -1,14 +0,0 @@ -# Backend -terraform { - # `backend` blocks do not support variables, so the following are hard-coded here: - # - S3 bucket name, which is created in modernisation-platform-account/s3.tf - backend "s3" { - acl = "bucket-owner-full-control" - bucket = "modernisation-platform-terraform-state" - dynamodb_table = "modernisation-platform-terraform-state-lock" - encrypt = true - key = "terraform.tfstate" - region = "eu-west-2" - workspace_key_prefix = "environments/members/tariff" # This will store the object as environments/members/tariff/${workspace}/terraform.tfstate - } -} diff --git a/terraform/environments/tariff/platform_base_variables.tf b/terraform/environments/tariff/platform_base_variables.tf deleted file mode 100644 index e5713ed9493..00000000000 --- a/terraform/environments/tariff/platform_base_variables.tf +++ /dev/null @@ -1,11 +0,0 @@ -variable "networking" { - - type = list(any) - -} - -variable "collaborator_access" { - type = string - default = "developer" - description = "Collaborators must specify which access level they are using, eg set an environment variable of export TF_VAR_collaborator_access=migration" -} diff --git a/terraform/environments/tariff/platform_data.tf b/terraform/environments/tariff/platform_data.tf deleted file mode 100644 index 9844360a8cd..00000000000 --- a/terraform/environments/tariff/platform_data.tf +++ /dev/null @@ -1,173 +0,0 @@ -# Current account data -data "aws_region" "current" {} - -data "aws_caller_identity" "current" {} - -# VPC and subnet data -data "aws_vpc" "shared" { - tags = { - "Name" = "${var.networking[0].business-unit}-${local.environment}" - } -} - -data "aws_subnets" "shared-data" { - filter { - name = "vpc-id" - values = [data.aws_vpc.shared.id] - } - tags = { - Name = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}-data*" - } -} - -data "aws_subnets" "shared-private" { - filter { - name = "vpc-id" - values = [data.aws_vpc.shared.id] - } - tags = { - Name = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}-private*" - } -} - -data "aws_subnets" "shared-public" { - filter { - name = "vpc-id" - values = [data.aws_vpc.shared.id] - } - tags = { - Name = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}-public*" - } -} - -data "aws_subnet" "data_subnets_a" { - vpc_id = data.aws_vpc.shared.id - tags = { - "Name" = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}-data-${data.aws_region.current.name}a" - } -} - -data "aws_subnet" "data_subnets_b" { - vpc_id = data.aws_vpc.shared.id - tags = { - "Name" = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}-data-${data.aws_region.current.name}b" - } -} - -data "aws_subnet" "data_subnets_c" { - vpc_id = data.aws_vpc.shared.id - tags = { - "Name" = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}-data-${data.aws_region.current.name}c" - } -} - -data "aws_subnet" "private_subnets_a" { - vpc_id = data.aws_vpc.shared.id - tags = { - "Name" = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}-private-${data.aws_region.current.name}a" - } -} - -data "aws_subnet" "private_subnets_b" { - vpc_id = data.aws_vpc.shared.id - tags = { - "Name" = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}-private-${data.aws_region.current.name}b" - } -} - -data "aws_subnet" "private_subnets_c" { - vpc_id = data.aws_vpc.shared.id - tags = { - "Name" = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}-private-${data.aws_region.current.name}c" - } -} - -data "aws_subnet" "public_subnets_a" { - vpc_id = data.aws_vpc.shared.id - tags = { - Name = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}-public-${data.aws_region.current.name}a" - } -} - -data "aws_subnet" "public_subnets_b" { - vpc_id = data.aws_vpc.shared.id - tags = { - Name = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}-public-${data.aws_region.current.name}b" - } -} - -data "aws_subnet" "public_subnets_c" { - vpc_id = data.aws_vpc.shared.id - tags = { - Name = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}-public-${data.aws_region.current.name}c" - } -} - -# Route53 DNS data -data "aws_route53_zone" "external" { - provider = aws.core-vpc - - name = "${var.networking[0].business-unit}-${local.environment}.modernisation-platform.service.justice.gov.uk." - private_zone = false -} - -data "aws_route53_zone" "inner" { - provider = aws.core-vpc - - name = "${var.networking[0].business-unit}-${local.environment}.modernisation-platform.internal." - private_zone = true -} - -data "aws_route53_zone" "network-services" { - provider = aws.core-network-services - - name = "modernisation-platform.service.justice.gov.uk." - private_zone = false -} - -# Shared KMS keys (per business unit) -data "aws_kms_key" "general_shared" { - key_id = "arn:aws:kms:eu-west-2:${local.environment_management.account_ids["core-shared-services-production"]}:alias/general-${var.networking[0].business-unit}" -} - -data "aws_kms_key" "ebs_shared" { - key_id = "arn:aws:kms:eu-west-2:${local.environment_management.account_ids["core-shared-services-production"]}:alias/ebs-${var.networking[0].business-unit}" -} - -data "aws_kms_key" "rds_shared" { - key_id = "arn:aws:kms:eu-west-2:${local.environment_management.account_ids["core-shared-services-production"]}:alias/rds-${var.networking[0].business-unit}" -} - -# State for core-network-services resource information -data "terraform_remote_state" "core_network_services" { - backend = "s3" - config = { - acl = "bucket-owner-full-control" - bucket = "modernisation-platform-terraform-state" - key = "environments/accounts/core-network-services/core-network-services-production/terraform.tfstate" - region = "eu-west-2" - encrypt = "true" - } -} - -data "aws_organizations_organization" "root_account" {} - -# Retrieve information about the modernisation platform account -data "aws_caller_identity" "modernisation_platform" { - provider = aws.modernisation-platform -} - -# caller account information to instantiate aws.oidc provider -data "aws_caller_identity" "original_session" { - provider = aws.original-session -} - -data "aws_iam_session_context" "whoami" { - provider = aws.original-session - arn = data.aws_caller_identity.original_session.arn -} - -# Get the environments file from the main repository -data "http" "environments_file" { - url = "https://raw.githubusercontent.com/ministryofjustice/modernisation-platform/main/environments/${local.application_name}.json" -} diff --git a/terraform/environments/tariff/platform_locals.tf b/terraform/environments/tariff/platform_locals.tf deleted file mode 100644 index 75b4a756417..00000000000 --- a/terraform/environments/tariff/platform_locals.tf +++ /dev/null @@ -1,38 +0,0 @@ -locals { - - application_name = "tariff" - - environment_management = jsondecode(data.aws_secretsmanager_secret_version.environment_management.secret_string) - - # Stores modernisation platform account id for setting up the modernisation-platform provider - modernisation_platform_account_id = data.aws_ssm_parameter.modernisation_platform_account_id.value - - # This takes the name of the Terraform workspace (e.g. core-vpc-production), strips out the application name (e.g. core-vpc), and checks if - # the string leftover is `-production`, if it isn't (e.g. core-vpc-non-production => -non-production) then it sets the var to false. - is-production = substr(terraform.workspace, length(local.application_name), length(terraform.workspace)) == "-production" - is-preproduction = substr(terraform.workspace, length(local.application_name), length(terraform.workspace)) == "-preproduction" - is-test = substr(terraform.workspace, length(local.application_name), length(terraform.workspace)) == "-test" - is-development = substr(terraform.workspace, length(local.application_name), length(terraform.workspace)) == "-development" - - # Merge tags from the environment json file with additional ones - tags = merge( - jsondecode(data.http.environments_file.response_body).tags, - { "is-production" = local.is-production }, - { "environment-name" = terraform.workspace }, - { "source-code" = "https://github.com/ministryofjustice/modernisation-platform-environments" } - ) - - environment = trimprefix(terraform.workspace, "${var.networking[0].application}-") - vpc_name = var.networking[0].business-unit - subnet_set = var.networking[0].set - vpc_all = "${local.vpc_name}-${local.environment}" - subnet_set_name = "${var.networking[0].business-unit}-${local.environment}-${var.networking[0].set}" - - is_live = [substr(terraform.workspace, length(local.application_name), length(terraform.workspace)) == "-production" || substr(terraform.workspace, length(local.application_name), length(terraform.workspace)) == "-preproduction" ? "live" : "non-live"] - provider_name = "core-vpc-${local.environment}" - - # environment specfic variables - # example usage: - # example_data = local.application_data.accounts[local.environment].example_var - application_data = fileexists("./application_variables.json") ? jsondecode(file("./application_variables.json")) : null -} diff --git a/terraform/environments/tariff/platform_providers.tf b/terraform/environments/tariff/platform_providers.tf deleted file mode 100644 index 828f987c7aa..00000000000 --- a/terraform/environments/tariff/platform_providers.tf +++ /dev/null @@ -1,58 +0,0 @@ -# AWS provider for the original session which you connect with -provider "aws" { - alias = "original-session" - region = "eu-west-2" -} - -# AWS provider for the workspace you're working in (every resource will default to using this, unless otherwise specified) -provider "aws" { - region = "eu-west-2" - assume_role { - role_arn = !can(regex("githubactionsrolesession|AdministratorAccess|user", data.aws_caller_identity.original_session.arn)) ? null : can(regex("user", data.aws_caller_identity.original_session.arn)) ? "arn:aws:iam::${local.environment_management.account_ids[terraform.workspace]}:role/${var.collaborator_access}" : "arn:aws:iam::${data.aws_caller_identity.original_session.id}:role/MemberInfrastructureAccess" - } -} - -# AWS provider for the Modernisation Platform, to get things from there if required -provider "aws" { - alias = "modernisation-platform" - region = "eu-west-2" - assume_role { - role_arn = "arn:aws:iam::${local.modernisation_platform_account_id}:role/modernisation-account-limited-read-member-access" - } -} - -# AWS provider for core-vpc-, to access resources in the core-vpc accounts -provider "aws" { - alias = "core-vpc" - region = "eu-west-2" - assume_role { - role_arn = !can(regex("githubactionsrolesession|AdministratorAccess", data.aws_caller_identity.original_session.arn)) ? "arn:aws:iam::${local.environment_management.account_ids[local.provider_name]}:role/member-delegation-read-only" : "arn:aws:iam::${local.environment_management.account_ids[local.provider_name]}:role/member-delegation-${local.vpc_name}-${local.environment}" - } -} - -# AWS provider for network services to enable dns entries for certificate validation to be created -provider "aws" { - alias = "core-network-services" - region = "eu-west-2" - assume_role { - role_arn = !can(regex("githubactionsrolesession|AdministratorAccess", data.aws_caller_identity.original_session.arn)) ? "arn:aws:iam::${local.environment_management.account_ids["core-network-services-production"]}:role/read-log-records" : "arn:aws:iam::${local.environment_management.account_ids["core-network-services-production"]}:role/modify-dns-records" - } -} - -# Provider for creating resources in us-east-1, eg ACM resources for CloudFront -provider "aws" { - alias = "us-east-1" - region = "us-east-1" - assume_role { - role_arn = !can(regex("githubactionsrolesession|AdministratorAccess|user", data.aws_caller_identity.original_session.arn)) ? null : can(regex("user", data.aws_caller_identity.original_session.arn)) ? "arn:aws:iam::${local.environment_management.account_ids[terraform.workspace]}:role/${var.collaborator_access}" : "arn:aws:iam::${data.aws_caller_identity.original_session.id}:role/MemberInfrastructureAccessUSEast" - } -} - -# Provider for reading resources from root account IdentityStore -provider "aws" { - region = "eu-west-2" - alias = "sso-readonly" - assume_role { - role_arn = "arn:aws:iam::${local.environment_management.aws_organizations_root_account_id}:role/ModernisationPlatformSSOReadOnly" - } -} diff --git a/terraform/environments/tariff/platform_secrets.tf b/terraform/environments/tariff/platform_secrets.tf deleted file mode 100644 index bb006856534..00000000000 --- a/terraform/environments/tariff/platform_secrets.tf +++ /dev/null @@ -1,17 +0,0 @@ -# Get modernisation account id from ssm parameter -data "aws_ssm_parameter" "modernisation_platform_account_id" { - provider = aws.original-session - name = "modernisation_platform_account_id" -} - -# Get secret by arn for environment management -data "aws_secretsmanager_secret" "environment_management" { - provider = aws.modernisation-platform - name = "environment_management" -} - -# Get latest secret value with ID from above. This secret stores account IDs for the Modernisation Platform sub-accounts -data "aws_secretsmanager_secret_version" "environment_management" { - provider = aws.modernisation-platform - secret_id = data.aws_secretsmanager_secret.environment_management.id -} diff --git a/terraform/environments/tariff/platform_versions.tf b/terraform/environments/tariff/platform_versions.tf deleted file mode 100644 index 6161ef3bc02..00000000000 --- a/terraform/environments/tariff/platform_versions.tf +++ /dev/null @@ -1,13 +0,0 @@ -terraform { - required_providers { - aws = { - version = "~> 5.0" - source = "hashicorp/aws" - } - http = { - version = "~> 3.0" - source = "hashicorp/http" - } - } - required_version = "~> 1.0" -} diff --git a/terraform/environments/tariff/s3.tf b/terraform/environments/tariff/s3.tf deleted file mode 100644 index fdf12c21f8d..00000000000 --- a/terraform/environments/tariff/s3.tf +++ /dev/null @@ -1,53 +0,0 @@ -module "s3-bucket" { - source = "github.com/ministryofjustice/modernisation-platform-terraform-s3-bucket?ref=v7.1.0" - - providers = { - # Default provider for replication to same region. Contact Mod Platform if replication to different region is required. - aws.bucket-replication = aws - } - bucket_name = "tariff-bucket" - replication_enabled = false - - lifecycle_rule = [ - { - id = "main" - enabled = "Enabled" - prefix = "" - - tags = { - rule = "log" - autoclean = "true" - } - - transition = [ - { - days = 90 - storage_class = "STANDARD_IA" - }, { - days = 365 - storage_class = "GLACIER" - } - ] - - expiration = { - days = 730 - } - - noncurrent_version_transition = [ - { - days = 90 - storage_class = "STANDARD_IA" - }, { - days = 365 - storage_class = "GLACIER" - } - ] - - noncurrent_version_expiration = { - days = 730 - } - } - ] - - tags = local.tags -} diff --git a/terraform/environments/tariff/secrets.tf b/terraform/environments/tariff/secrets.tf deleted file mode 100644 index a6a94d9c098..00000000000 --- a/terraform/environments/tariff/secrets.tf +++ /dev/null @@ -1 +0,0 @@ -#### This file can be used to store secrets specific to the member account #### From cace4e973b5a13677b3bf5af1a3bfd5931d6e24f Mon Sep 17 00:00:00 2001 From: SteveLinden Date: Wed, 12 Jun 2024 16:35:35 +0100 Subject: [PATCH 2/2] Delete .github/workflows/reusable_terraform_plan_apply.yml Shouldn't be in the request --- .../reusable_terraform_plan_apply.yml | 323 ------------------ 1 file changed, 323 deletions(-) delete mode 100644 .github/workflows/reusable_terraform_plan_apply.yml diff --git a/.github/workflows/reusable_terraform_plan_apply.yml b/.github/workflows/reusable_terraform_plan_apply.yml deleted file mode 100644 index 0fdf3917f76..00000000000 --- a/.github/workflows/reusable_terraform_plan_apply.yml +++ /dev/null @@ -1,323 +0,0 @@ ---- -name: terraform plan apply - -# Reusable pipeline for running terraform plan and/or apply on a single -# modernisation platform application environment, e.g. nomis-test. -# -# Constraints: -# - The terraform state must be in a workspace with the same name as the -# application account, e.g. ${application}-${environment} -# -# Features: -# - redacts plan and apply output for use in public repo -# - the apply step sets a deployment environment so a separate approval -# step can be added in the github UI. -# - the apply step is skipped if there is nothing to do in the plan (to -# avoid unnecessary apply approvals) -# - you can optional refresh state as part of the plan (useful if there -# are often AWS changes outside of terraform, and you don't want to -# see this in the plan step) -# - you can optionally post PR plans into the corresponding PR -# - colour output is used unless a PR plan is going to be posted into -# a PR. - -on: - workflow_call: - inputs: - application: - type: string - required: true - description: "Name of the application, e.g. nomis" - environment: - type: string - required: true - description: "Name of the environment, e.g. development" - action: - type: string - required: false - description: "Set to plan or plan_apply" - default: plan - terraform_version: - type: string - required: false - description: "The terraform version to use" - default: "~1" - plan_apply_tfargs: - type: string - required: false - description: "Any additional terraform arguments to be passed in to terraform plan/apply, e.g. -var 'foo=bar'" - default: "" - do_state_refresh_on_plan: - type: boolean - required: false - description: "Set to true to do a state refresh prior to the plan" - default: false - post_plan_to_pr: - type: boolean - required: false - description: "Set to true to post terraform plan as a comment to the PR" - default: false - secrets: - modernisation_platform_environments: - required: true - pipeline_github_token: - required: true - -env: - ACCOUNT_NAME: "${{ inputs.application }}-${{ inputs.environment }}" - WORKSPACE_NAME: "${{ inputs.application }}-${{ inputs.environment }}" - ENVIRONMENT_MANAGEMENT: "${{ secrets.modernisation_platform_environments }}" - GITHUB_TOKEN: "${{ secrets.pipeline_github_token }}" - -jobs: - plan: - name: "plan" - runs-on: ubuntu-latest - outputs: - plan_exitcode: "${{ steps.plan.outputs.exitcode }}" - steps: - - name: Debug - run: | - echo "application=${{ inputs.application }}" - echo "environment=${{ inputs.environment }}" - echo "action=${{ inputs.action }}" - echo "init_plan_apply_tfargs=${{ inputs.init_plan_apply_tfargs }}" - echo "plan_apply_tfargs=${{ inputs.plan_apply_tfargs }}" - echo "do_state_refresh_on_plan=${{ inputs.do_state_refresh_on_plan }}" - echo "post_plan_to_pr=${{ inputs.post_plan_to_pr }}" - - - name: Checkout Repository - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - - - name: Get AWS Account Number - run: | - ACCOUNT_NUMBER=$(jq -r -e --arg account_name "${ACCOUNT_NAME}" '.account_ids[$account_name]' <<< $ENVIRONMENT_MANAGEMENT) - echo "ACCOUNT_NUMBER=${ACCOUNT_NUMBER}" >> $GITHUB_ENV - - - name: Get Backend AWS Account Number - run: | - BACKEND_NUMBER=$(jq -r -e '.modernisation_platform_account_id' <<< $ENVIRONMENT_MANAGEMENT) - echo "BACKEND_NUMBER=${BACKEND_NUMBER}" >> $GITHUB_ENV - - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1 - with: - role-to-assume: "arn:aws:iam::${{ env.ACCOUNT_NUMBER }}:role/github-actions" - role-session-name: githubactionsrolesession - aws-region: "eu-west-2" - - - name: Setup Terraform - uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1 - with: - terraform_version: "${{ inputs.terraform_version }}" - terraform_wrapper: false - - - name: Terraform Init - working-directory: "terraform/environments/${{ inputs.application }}" - run: | - terraform --version - echo "terraform init -backend-config=assume_role={role_arn=\"arn:aws:iam::${{env.BACKEND_NUMBER}}:role/modernisation-account-terraform-state-member-access\"}" - terraform init -backend-config=assume_role={role_arn=\"arn:aws:iam::${{env.BACKEND_NUMBER}}:role/modernisation-account-terraform-state-member-access\"} - - - name: Terraform Workspace Select - working-directory: "terraform/environments/${{ inputs.application }}" - run: | - terraform workspace select "${WORKSPACE_NAME}" - - - name: Terraform State Refresh (Optional) - if: inputs.do_state_refresh_on_plan == true - working-directory: "terraform/environments/${{ inputs.application }}" - run: | - set -o pipefail - tf_args="${{ inputs.init_plan_apply_tfargs }} ${{ inputs.plan_apply_tfargs }}" - echo "terraform apply -refresh-only -auto-approve ${tf_args}" - terraform apply -refresh-only -auto-approve ${tf_args} | bash ${GITHUB_WORKSPACE}/scripts/redact-output.sh - - - name: Terraform Plan - id: plan - env: - POST_PLAN_TO_PR: "${{ github.event_name == 'pull_request' && inputs.post_plan_to_pr == true }}" - working-directory: "terraform/environments/${{ inputs.application }}" - run: | - set -o pipefail - exitcode=0 - tf_args="-detailed-exitcode ${{ inputs.init_plan_apply_tfargs }} ${{ inputs.plan_apply_tfargs }}" - [[ ${POST_PLAN_TO_PR} == 'true' ]] && tf_args="${tf_args} -no-color" - [[ ${{ inputs.do_state_refresh_on_plan }} == 'true' ]] && tf_args="${tf_args} -refresh=false" - echo "terraform plan ${tf_args}" - terraform plan ${tf_args} -out=tfplan | bash ${GITHUB_WORKSPACE}/scripts/redact-output.sh | tee tfplan.txt || exitcode=$? - terraform show -json tfplan > tfplan.json - echo "exitcode=${exitcode}" # 0=clean plan, 1=error, 2=stuff in plan - echo "exitcode=${exitcode}" >> $GITHUB_OUTPUT - (( exitcode == 1 )) && exit 1 || exit 0 - - - name: Evaluate Terraform Plan - if: github.event_name == 'pull_request' && steps.plan.outputs.exitcode == '2' - id: evaluate_terraform_plan - working-directory: "terraform/environments/${{ inputs.application }}" - shell: bash - run: | - bash -x ${GITHUB_WORKSPACE}/scripts/terraform-plan-evaluator.sh tfplan.json - - - name: Create Plan PR message (Optional) - if: github.event_name == 'pull_request' && steps.plan.outputs.exitcode == '2' && inputs.post_plan_to_pr == true - working-directory: "terraform/environments/${{ inputs.application }}" - run: | - comment() { - url="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - len=$(cat tfplan.txt | wc -c) - echo '**`${{ env.WORKSPACE_NAME }}`** terraform plan on `${{ github.event_name }}` event [#${{ github.run_number }}]('${url}')' - echo - echo '```' - head -c 65476 tfplan.txt | sed -n '/Terraform will perform/,$p' - echo - echo '```' - if [[ $len -gt 65476 ]]; then - echo "** Truncated output. See $url for the rest **" - fi - } - echo 'TF_PLAN_OUT<> $GITHUB_ENV - comment >> $GITHUB_ENV - echo 'EOF' >> $GITHUB_ENV - - - name: Hide Previous PR comment (Optional) - if: ${{ github.event_name == 'pull_request' }} - working-directory: "scripts/minimise-comments" - env: - COMMENT_BODY_CONTAINS: "**`${{ env.WORKSPACE_NAME }}`**" - PR_NUMBER: "${{ github.event.pull_request.number }}" - run: | - go build - ./minimise-comments - - - name: Post Plan to PR (Optional) - if: github.event_name == 'pull_request' && steps.plan.outputs.exitcode == '2' && inputs.post_plan_to_pr == true - env: - message: "${{ env.TF_PLAN_OUT }}" - run: | - escaped_message=$(echo "$message" | jq -Rsa .) - curl -sS -X POST \ - -H "Accept: application/vnd.github+json" \ - -H "Authorization: Bearer ${{ env.GITHUB_TOKEN }}" \ - "https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" \ - -d '{"body":'"${escaped_message}"'}' - - - name: Check for Approval - id: check_approval - if: github.event_name == 'pull_request' && steps.evaluate_terraform_plan.outputs.resources_found == 'true' - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - with: - github-token: ${{ secrets.pipeline_github_token }} - script: | - const orgName = 'ministryofjustice'; - const teamSlug = 'modernisation-platform'; - - const {data: reviews} = await github.rest.pulls.listReviews({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.payload.pull_request.number - }); - - const {data: team_members} = await github.rest.teams.listMembersInOrg({ - org: orgName, - team_slug: teamSlug - }); - - const teamMemberLogins = team_members.map(member => member.login); - const approved = reviews.some(review => review.state === 'APPROVED' && teamMemberLogins.includes(review.user.login)); - - if (approved) { - core.notice('Pull request approved by a member of @ministryofjustice/modernisation-platform'); - } - else { - core.setFailed('Terraform plan evaluation detected changes to resources that require approval from a member of @ministryofjustice/modernisation-platform - please contact #ask-modernisation-platform for assistance' - # NEW code here); - - await github.rest.pulls.createReview({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.payload.pull_request.number, - event: 'REQUEST_CHANGES', - body: 'Terraform plan evaluation detected changes to resources that require approval from @ministryofjustice/modernsation-platform - please contact #ask-modernisation-platform for assistance' - # NEW code here - }); - } - - - name: Comment if PR Requires Approval - id: comment_if_not_approved - if: failure() && github.event_name == 'pull_request' && steps.check_approval.outcome == 'failure' - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - with: - github-token: ${{ secrets.pipeline_github_token }} - script: | - const owner = context.repo.owner; - const repo = context.repo.repo; - - await github.rest.issues.createComment({ - owner: owner, - repo: repo, - issue_number: context.payload.pull_request.number, - body: `@${context.actor} Terraform plan evaluation detected changes to resources that require approval from a member of @ministryofjustice/modernisation-platform - please contact #ask-modernisation-platform for assistance` - # NEW code here - }); - - apply: - name: "apply" - needs: plan - if: inputs.action == 'plan_apply' && needs.plan.outputs.plan_exitcode == '2' - runs-on: ubuntu-latest - environment: "${{ inputs.application }}-${{ inputs.environment }}" - steps: - - name: Checkout Repository - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4 - - - name: Get AWS Account Number - run: | - ACCOUNT_NUMBER=$(jq -r -e --arg account_name "${ACCOUNT_NAME}" '.account_ids[$account_name]' <<< $ENVIRONMENT_MANAGEMENT) - echo "ACCOUNT_NUMBER=${ACCOUNT_NUMBER}" >> $GITHUB_ENV - - - name: Get Backend AWS Account Number - run: | - BACKEND_NUMBER=$(jq -r -e '.modernisation_platform_account_id' <<< $ENVIRONMENT_MANAGEMENT) - echo "BACKEND_NUMBER=${BACKEND_NUMBER}" >> $GITHUB_ENV - - - name: Configure AWS Credentials - uses: aws-actions/configure-aws-credentials@010d0da01d0b5a38af31e9c3470dbfdabdecca3a # v4.0.1 - with: - role-to-assume: "arn:aws:iam::${{ env.ACCOUNT_NUMBER }}:role/github-actions" - role-session-name: githubactionsrolesession - aws-region: "eu-west-2" - - - name: Setup Terraform - uses: hashicorp/setup-terraform@651471c36a6092792c552e8b1bef71e592b462d8 # v3.1.1 - with: - terraform_version: "${{ inputs.terraform_version }}" - terraform_wrapper: false - - - name: Terraform Init - working-directory: "terraform/environments/${{ inputs.application }}" - run: | - terraform --version - echo "terraform init -backend-config=assume_role={role_arn=\"arn:aws:iam::${{env.BACKEND_NUMBER}}:role/modernisation-account-terraform-state-member-access\"}" - terraform init -backend-config=assume_role={role_arn=\"arn:aws:iam::${{env.BACKEND_NUMBER}}:role/modernisation-account-terraform-state-member-access\"} - - - name: Terraform Workspace Select - working-directory: "terraform/environments/${{ inputs.application }}" - run: | - terraform workspace select "${WORKSPACE_NAME}" - - - name: Terraform Plan - working-directory: "terraform/environments/${{ inputs.application }}" - run: | - set -o pipefail - tf_args="-out x.tfplan ${{ inputs.init_plan_apply_tfargs }} ${{ inputs.plan_apply_tfargs }}" - echo "terraform plan ${tf_args}" - terraform plan ${tf_args} | bash ${GITHUB_WORKSPACE}/scripts/redact-output.sh - - - name: Terraform Apply - working-directory: "terraform/environments/${{ inputs.application }}" - run: | - set -o pipefail - tf_args="${{ inputs.init_plan_apply_tfargs }} ${{ inputs.plan_apply_tfargs }} x.tfplan" - echo "terraform apply ${tf_args}" - terraform apply ${tf_args} | bash ${GITHUB_WORKSPACE}/scripts/redact-output.sh