diff --git a/Makefile b/Makefile index c56fd6a..12a72b6 100644 --- a/Makefile +++ b/Makefile @@ -106,3 +106,31 @@ build: check-links: build bundle exec ruby -rhtml-proofer -e "HTMLProofer.check_directory('./build',{:hydra => { :max_concurrency => 1 }}).run" + +domains-infra-init: domains composed-variables set-azure-account + ./bin/terrafile -p terraform/domains/infrastructure/vendor/modules -f terraform/domains/infrastructure/config/zones_Terrafile + + terraform -chdir=terraform/domains/infrastructure init -reconfigure -upgrade \ + -backend-config=resource_group_name=${RESOURCE_GROUP_NAME} \ + -backend-config=storage_account_name=${STORAGE_ACCOUNT_NAME} \ + -backend-config=key=domains_infrastructure.tfstate + +domains-infra-plan: domains composed-variables domains-infra-init + terraform -chdir=terraform/domains/infrastructure plan -var-file config/zones.tfvars.json + +domains-infra-apply: domains composed-variables domains-infra-init + terraform -chdir=terraform/domains/infrastructure apply -var-file config/zones.tfvars.json ${AUTO_APPROVE} + +domains-init: domains set-azure-account + ./bin/terrafile -p terraform/domains/environment_domains/vendor/modules -f terraform/domains/environment_domains/config/${CONFIG}_Terrafile + + terraform -chdir=terraform/domains/environment_domains init -upgrade -reconfigure \ + -backend-config=resource_group_name=${RESOURCE_GROUP_NAME} \ + -backend-config=storage_account_name=${STORAGE_ACCOUNT_NAME} \ + -backend-config=key=${ENVIRONMENT}.tfstate + +domains-plan: domains-init + terraform -chdir=terraform/domains/environment_domains plan -var-file config/${CONFIG}.tfvars.json + +domains-apply: domains-init + terraform -chdir=terraform/domains/environment_domains apply -var-file config/${CONFIG}.tfvars.json ${AUTO_APPROVE} diff --git a/Makefile.bak b/Makefile.bak new file mode 100644 index 0000000..c43c445 --- /dev/null +++ b/Makefile.bak @@ -0,0 +1,140 @@ +TERRAFILE_VERSION=0.8 +ARM_TEMPLATE_TAG=1.1.10 +RG_TAGS={"Product" : "Teacher services cloud"} +REGION=UK South +SERVICE_NAME=technical-guidance +SERVICE_SHORT=techg +DOCKER_REPOSITORY=ghcr.io/dfe-digital/technical-guidance + +help: + @grep -E '^[a-zA-Z\._\-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +.PHONY: development +development: test-cluster + $(eval include global_config/development.sh) + +review: test-cluster + $(if ${PR_NUMBER},,$(error Missing PR_NUMBER)) + $(eval ENVIRONMENT=${PR_NUMBER}) + $(eval TF_VAR_ENVIRONMENT=${PR_NUMBER}) + $(eval include global_config/review.sh) + +production: production-cluster + $(if $(or ${SKIP_CONFIRM}, ${CONFIRM_PRODUCTION}), , $(error Missing CONFIRM_PRODUCTION=yes)) + $(eval include global_config/production.sh) + +domains: + $(eval include global_config/domains.sh) + +composed-variables: + $(eval RESOURCE_GROUP_NAME=${AZURE_RESOURCE_PREFIX}-${SERVICE_SHORT}-${CONFIG_SHORT}-rg) + $(eval KEYVAULT_NAMES='("${AZURE_RESOURCE_PREFIX}-${SERVICE_SHORT}-${CONFIG_SHORT}-app-kv", "${AZURE_RESOURCE_PREFIX}-${SERVICE_SHORT}-${CONFIG_SHORT}-inf-kv")') + $(eval STORAGE_ACCOUNT_NAME=${AZURE_RESOURCE_PREFIX}${SERVICE_SHORT}${CONFIG_SHORT}tfsa) + +ci: + $(eval AUTO_APPROVE=-auto-approve) + $(eval SKIP_AZURE_LOGIN=true) + $(eval SKIP_CONFIRM=true) + +bin/terrafile: ## Install terrafile to manage terraform modules + curl -sL https://github.com/coretech/terrafile/releases/download/v${TERRAFILE_VERSION}/terrafile_${TERRAFILE_VERSION}_$$(uname)_x86_64.tar.gz \ + | tar xz -C ./bin terrafile + +set-azure-account: + [ "${SKIP_AZURE_LOGIN}" != "true" ] && az account set -s ${AZURE_SUBSCRIPTION} || true + +terraform-init: composed-variables bin/terrafile set-azure-account + $(if ${DOCKER_IMAGE_TAG}, , $(eval DOCKER_IMAGE_TAG=main)) + + ./bin/terrafile -p terraform/application/vendor/modules -f terraform/application/config/$(CONFIG)_Terrafile + terraform -chdir=terraform/application init -upgrade -reconfigure \ + -backend-config=resource_group_name=${RESOURCE_GROUP_NAME} \ + -backend-config=storage_account_name=${STORAGE_ACCOUNT_NAME} \ + -backend-config=key=${ENVIRONMENT}_kubernetes.tfstate + $(eval export TF_VAR_environment=${ENVIRONMENT}) + $(eval export TF_VAR_azure_resource_prefix=${AZURE_RESOURCE_PREFIX}) + $(eval export TF_VAR_config_short=${CONFIG_SHORT}) + $(eval export TF_VAR_service_name=${SERVICE_NAME}) + $(eval export TF_VAR_service_short=${SERVICE_SHORT}) + $(eval export TF_VAR_docker_image=${DOCKER_REPOSITORY}:${DOCKER_IMAGE_TAG}) + +terraform-plan: terraform-init + terraform -chdir=terraform/application plan -var-file "config/${CONFIG}.tfvars.json" + +terraform-apply: terraform-init + terraform -chdir=terraform/application apply -var-file "config/${CONFIG}.tfvars.json" ${AUTO_APPROVE} + +terraform-destroy: terraform-init + terraform -chdir=terraform/application destroy -var-file "config/${CONFIG}.tfvars.json" ${AUTO_APPROVE} + +set-what-if: + $(eval WHAT_IF=--what-if) + +arm-deployment: composed-variables set-azure-account + $(if ${DISABLE_KEYVAULTS},, $(eval KV_ARG=keyVaultNames=${KEYVAULT_NAMES})) + $(if ${ENABLE_KV_DIAGNOSTICS}, $(eval KV_DIAG_ARG=enableDiagnostics=${ENABLE_KV_DIAGNOSTICS} logAnalyticsWorkspaceName=${LOG_ANALYTICS_WORKSPACE_NAME}),) + + az deployment sub create --name "resourcedeploy-tsc-$(shell date +%Y%m%d%H%M%S)" \ + -l "${REGION}" --template-uri "https://raw.githubusercontent.com/DFE-Digital/tra-shared-services/${ARM_TEMPLATE_TAG}/azure/resourcedeploy.json" \ + --parameters "resourceGroupName=${RESOURCE_GROUP_NAME}" 'tags=${RG_TAGS}' \ + "tfStorageAccountName=${STORAGE_ACCOUNT_NAME}" "tfStorageContainerName=terraform-state" \ + ${KV_ARG} \ + ${KV_DIAG_ARG} \ + "enableKVPurgeProtection=${KV_PURGE_PROTECTION}" \ + ${WHAT_IF} + +deploy-arm-resources: arm-deployment ## Validate ARM resource deployment. Usage: make domains validate-arm-resources + +validate-arm-resources: set-what-if arm-deployment ## Validate ARM resource deployment. Usage: make domains validate-arm-resources + +domains-infra-init: bin/terrafile domains composed-variables set-azure-account + ./bin/terrafile -p terraform/domains/infrastructure/vendor/modules -f terraform/domains/infrastructure/config/zones_Terrafile + + terraform -chdir=terraform/domains/infrastructure init -reconfigure -upgrade \ + -backend-config=resource_group_name=${RESOURCE_GROUP_NAME} \ + -backend-config=storage_account_name=${STORAGE_ACCOUNT_NAME} \ + -backend-config=key=domains_infrastructure.tfstate + +domains-infra-plan: domains domains-infra-init ## Terraform plan for DNS infrastructure (zone and front door. Usage: make domains-infra-plan + terraform -chdir=terraform/domains/infrastructure plan -var-file config/zones.tfvars.json + +domains-infra-apply: domains domains-infra-init ## Terraform apply for DNS infrastructure (zone and front door). Usage: make domains-infra-apply + terraform -chdir=terraform/domains/infrastructure apply -var-file config/zones.tfvars.json ${AUTO_APPROVE} + +domains-init: bin/terrafile domains composed-variables set-azure-account + ./bin/terrafile -p terraform/domains/environment_domains/vendor/modules -f terraform/domains/environment_domains/config/${CONFIG}_Terrafile + + terraform -chdir=terraform/domains/environment_domains init -upgrade -reconfigure \ + -backend-config=resource_group_name=${RESOURCE_GROUP_NAME} \ + -backend-config=storage_account_name=${STORAGE_ACCOUNT_NAME} \ + -backend-config=key=${ENVIRONMENT}.tfstate + +domains-plan: domains-init ## Terraform plan for DNS environment domains. Usage: make development domains domains-plan + terraform -chdir=terraform/domains/environment_domains plan -var-file config/${CONFIG}.tfvars.json + +domains-apply: domains-init ## Terraform apply for DNS environment domains. Usage: make development domains domains-apply + terraform -chdir=terraform/domains/environment_domains apply -var-file config/${CONFIG}.tfvars.json ${AUTO_APPROVE} + +test-cluster: + $(eval CLUSTER_RESOURCE_GROUP_NAME=s189t01-tsc-ts-rg) + $(eval CLUSTER_NAME=s189t01-tsc-test-aks) + +production-cluster: + $(eval CLUSTER_RESOURCE_GROUP_NAME=s189p01-tsc-pd-rg) + $(eval CLUSTER_NAME=s189p01-tsc-production-aks) + +get-cluster-credentials: set-azure-account + az aks get-credentials --overwrite-existing -g ${CLUSTER_RESOURCE_GROUP_NAME} -n ${CLUSTER_NAME} + +bin/konduit.sh: + curl -s https://raw.githubusercontent.com/DFE-Digital/teacher-services-cloud/main/scripts/konduit.sh -o bin/konduit.sh \ + && chmod +x bin/konduit.sh +server: + bundle exec middleman server --verbose + +.PHONY: build +build: + rm -rf build && bundle exec middleman build --verbose + +check-links: build + bundle exec ruby -rhtml-proofer -e "HTMLProofer.check_directory('./build',{:hydra => { :max_concurrency => 1 }}).run" diff --git a/global_config/domains.sh b/global_config/domains.sh new file mode 100644 index 0000000..a7b7641 --- /dev/null +++ b/global_config/domains.sh @@ -0,0 +1,4 @@ +AZURE_SUBSCRIPTION=s189-teacher-services-cloud-production +AZURE_RESOURCE_PREFIX=s189p01 +CONFIG_SHORT=dom +DISABLE_KEYVAULTS=true diff --git a/terraform/domains/environment_domains/config/development.json b/terraform/domains/environment_domains/config/development.json new file mode 100644 index 0000000..9e760df --- /dev/null +++ b/terraform/domains/environment_domains/config/development.json @@ -0,0 +1,16 @@ +{ + "hosted_zone": { + "technical-guidance.education.gov.uk": { + "front_door_name": "s189p01-techg-domains-fd", + "resource_group_name": "s189p01-techg-domains-rg", + "domains": [ + "apex" + ], + "cached_paths": [ + "/assets/*" + ], + "environment_short": "dv", + "origin_hostname": "technical-guidance-development.test.teacherservices.cloud" + } + } +} diff --git a/terraform/domains/environment_domains/config/development_Terrafile b/terraform/domains/environment_domains/config/development_Terrafile new file mode 100644 index 0000000..58e60b3 --- /dev/null +++ b/terraform/domains/environment_domains/config/development_Terrafile @@ -0,0 +1,3 @@ +domains: + source: "https://github.com/DFE-Digital/terraform-modules" + version: "stable" diff --git a/terraform/domains/environment_domains/config/production.tfvars.json b/terraform/domains/environment_domains/config/production.tfvars.json new file mode 100644 index 0000000..27301bc --- /dev/null +++ b/terraform/domains/environment_domains/config/production.tfvars.json @@ -0,0 +1,16 @@ +{ + "hosted_zone": { + "technical-guidance.education.gov.uk": { + "front_door_name": "s189p01-techg-domains-fd", + "resource_group_name": "s189p01-techg-domains-rg", + "domains": [ + "apex" + ], + "cached_paths": [ + "/assets/*" + ], + "environment_short": "pd", + "origin_hostname": "technical-guidance-production.teacherservices.cloud" + } + } +} diff --git a/terraform/domains/environment_domains/config/production_Terrafile b/terraform/domains/environment_domains/config/production_Terrafile new file mode 100644 index 0000000..58e60b3 --- /dev/null +++ b/terraform/domains/environment_domains/config/production_Terrafile @@ -0,0 +1,3 @@ +domains: + source: "https://github.com/DFE-Digital/terraform-modules" + version: "stable" diff --git a/terraform/domains/environment_domains/main.tf b/terraform/domains/environment_domains/main.tf new file mode 100644 index 0000000..2664ddc --- /dev/null +++ b/terraform/domains/environment_domains/main.tf @@ -0,0 +1,61 @@ +# Used to create domains to be managed by front door. +module "domains" { + for_each = var.hosted_zone + source = "./vendor/modules/domains//domains/environment_domains" + zone = each.key + front_door_name = each.value.front_door_name + resource_group_name = each.value.resource_group_name + domains = each.value.domains + environment = each.value.environment_short + host_name = each.value.origin_hostname + null_host_header = try(each.value.null_host_header, false) + cached_paths = try(each.value.cached_paths, []) +} + +data "azurerm_cdn_frontdoor_profile" "main" { + name = var.front_door_name + resource_group_name = var.resource_group_name +} + +data "azurerm_linux_web_app" "app" { + provider = azurerm.app_subcription + name = var.app_name + resource_group_name = var.app_resource_group_name +} + +data "azurerm_dns_zone" "main" { + name = var.zone + resource_group_name = var.resource_group_name +} + +resource "azurerm_cdn_frontdoor_rule_set" "ruleset" { + name = var.environment_short + cdn_frontdoor_profile_id = data.azurerm_cdn_frontdoor_profile.main.id +} + +resource "azurerm_cdn_frontdoor_rule" "rule" { + for_each = var.redirect_rules + depends_on = [module.domains] + name = replace( + replace(each.key, ".", ""), + "-", "") + cdn_frontdoor_rule_set_id = azurerm_cdn_frontdoor_rule_set.ruleset.id + order = 1 + behavior_on_match = "Continue" + + actions { + + url_redirect_action { + redirect_type = "Moved" + redirect_protocol = "Https" + destination_hostname = each.value + } + } + + conditions { + host_name_condition { + operator = "Equal" + match_values = [each.key] + } + } +} diff --git a/terraform/domains/environment_domains/terraform.tf b/terraform/domains/environment_domains/terraform.tf new file mode 100644 index 0000000..0fb3339 --- /dev/null +++ b/terraform/domains/environment_domains/terraform.tf @@ -0,0 +1,19 @@ +terraform { + + required_version = "= 1.6.4" + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "3.82.0" + } + } + backend "azurerm" { + container_name = "terraform-state" + } +} + +provider "azurerm" { + features {} + + skip_provider_registration = true +} diff --git a/terraform/domains/environment_domains/variables.tf b/terraform/domains/environment_domains/variables.tf new file mode 100644 index 0000000..c256d84 --- /dev/null +++ b/terraform/domains/environment_domains/variables.tf @@ -0,0 +1,11 @@ +variable "hosted_zone" { + type = map(any) + default = {} +} +variable "zone" {} +variable "front_door_name" {} +variable "environment_short" {} +variable "resource_group_name" {} +variable "redirect_rules" { + default = {} +} diff --git a/terraform/domains/infrastructure/config/zones.tfvars.json b/terraform/domains/infrastructure/config/zones.tfvars.json new file mode 100644 index 0000000..7b8123f --- /dev/null +++ b/terraform/domains/infrastructure/config/zones.tfvars.json @@ -0,0 +1,11 @@ +{ + "hosted_zone": { + "technical-guidance.education.gov.uk": { + "caa_records": {}, + "txt_records": {}, + "resource_group_name": "s189p01-techg-dom-rg", + "front_door_name": "s189p01-techg-dom-fd" + } + }, + "deploy_default_records": false + } diff --git a/terraform/domains/infrastructure/config/zones_Terrafile b/terraform/domains/infrastructure/config/zones_Terrafile new file mode 100644 index 0000000..58e60b3 --- /dev/null +++ b/terraform/domains/infrastructure/config/zones_Terrafile @@ -0,0 +1,3 @@ +domains: + source: "https://github.com/DFE-Digital/terraform-modules" + version: "stable" diff --git a/terraform/domains/infrastructure/main.tf b/terraform/domains/infrastructure/main.tf new file mode 100644 index 0000000..da091f5 --- /dev/null +++ b/terraform/domains/infrastructure/main.tf @@ -0,0 +1,5 @@ +module "domains_infrastructure" { + source = "./vendor/modules/domains//domains/infrastructure" + hosted_zone = var.hosted_zone + deploy_default_records = var.deploy_default_records +} diff --git a/terraform/domains/infrastructure/terraform.tf b/terraform/domains/infrastructure/terraform.tf new file mode 100644 index 0000000..65b9162 --- /dev/null +++ b/terraform/domains/infrastructure/terraform.tf @@ -0,0 +1,19 @@ +terraform { + required_version = "= 1.6.4" + + required_providers { + azurerm = { + source = "hashicorp/azurerm" + version = "3.82.0" + } + } + backend "azurerm" { + container_name = "terraform-state" + } +} + +provider "azurerm" { + features {} + + skip_provider_registration = true +} diff --git a/terraform/domains/infrastructure/variables.tf b/terraform/domains/infrastructure/variables.tf new file mode 100644 index 0000000..8d91472 --- /dev/null +++ b/terraform/domains/infrastructure/variables.tf @@ -0,0 +1,7 @@ +variable "hosted_zone" { + type = map(any) +} + +variable "deploy_default_records" { + default = true +}