Cloud Standard¶
This standard is for management of the creation of resources using terraform.
Purpose¶
The purpose of the standard is outline the NHS BSA standards for managing the deployment of resources into Cloud environments using terraform. It covers:
- Structuring terraform repositories.
- Use of modules within in terraform.
- Use of terraform workspaces to manage deployments across different environments.
- Backend file creation.
- Provider file usage.
- Pipeline files.
The standard is in place to allow Platform Engineers to move across BSA projects with ease, knowing that a standard pattern has been adopted across the organisation.
Requirement¶
Structuring terraform repositories¶
The structure of terraform repositories should follow the pattern outlined below:
- This can be a single repository for all infrastructure terraform or can be broken down into smaller repositories. For projects with multiples components you may have a shared infrastructure repository and repositories for specific components. Fo example VDPS (see link below) has a main infrastructure repository and then respositories for specific components of the project. These component repositories have the required components specific to that part of the project such as lambda functions, api gateways, dynamodb tables.
- Each repository should have a clear README file outlining the purpose of the repository, how to use it, and any specific instructions for deployment.
Use of modules with terraform¶
- Platform Engineers should use modules from Terraform AWS Modules (https://registry.terraform.io/namespaces/terraform-aws-modules) wherever possible rather than creating individual resources.
- Module versions should be hard coded to avoid issues with module changes at later dates.
- Platform Engineers should avoid creating their own module structures.
User of terraform workspaces to manage deployments across different environments¶
- The standard NHS BSA terraform Gitlab pipeline file utilises terraform workspaces. This is explained further in the Pipeline files section of this page.
- Variables for the different environments are implemented as below:
variable "service_name" {
default = {
dev = "replace-with-service-short-name"
test = "replace-with-service-short-name"
stage = "replace-with-service-short-name"
prod = "replace-with-service-short-name"
}
}
module "acm" {
source = "terraform-aws-modules/acm/aws"
version = "~> 4.0"
domain_name = var.domain_name[terraform.workspace]
validate_certificate = var.validate_certificate[terraform.workspace]
create_route53_records = false
validation_record_fqdns = module.route53_records.validation_route53_record_fqdns
}
The use of [terraform.workspace] when using the variables will utilise the correct variable value for the workspace being deployed in.
Backend file creation¶
- The standard NHS BSA terraform Gitlab pipeline file utilises an s3 backend for storing the terraform state files. Using terraform workspaces in the Gitlab pipeline creates the seperate state files. This is explained further in the page on terraform state files. An example backend.tf file can be found below.
terraform {
backend "s3" {
bucket = "nhsbsa-845930604129-replace-terraform" # change word replace with area i.e. citizen
key = "${var.service_line[terraform.workspace]}/${var.service_name[terraform.workspace]}/${var.service_name[terraform.workspace]}-infrastructure.tfstate"
dynamodb_table = "terraform_state"
region = "eu-west-2"
}
}
Provider file usage¶
- The standard NHS BSA terraform Gitlab pipeline file utilises a provider.tf file which contains the required providers for the terraform deployment. An example provider.tf file can be found below.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.67.0"
}
}
}
provider "aws" {
region = "eu-west-2"
assume_role {
role_arn = "arn:aws:iam::${var.workspace_account_ids[terraform.workspace]}:role/NHSBSA_GitLabRunner"
}
default_tags {
tags = {
Environment = "${var.environment[terraform.workspace]}"
Business-Service = "${var.service[terraform.workspace]}"
Service-Line = "${var.service_line[terraform.workspace]}"
Terraform = "true"
Department = "${var.department[terraform.workspace]}"
}
}
}
provider "aws" {
region = "eu-west-2"
alias = "assurance"
assume_role {
role_arn = "arn:aws:iam::951392668072:role/NHSBSA_Route53"
}
}
Pipeline files¶
- The standard NHS BSA terraform Gitlab pipeline file utilises a .gitlab-ci.yml file which contains the required stages for the terraform deployment. An example .gitlab-ci.yml file can be found below.
include:
- project: nhsbsa/platform-services/pipeline-templates/terraform
file: terraform-job.gitlab-ci.yml
# - template: Terraform/Base.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Terraform/Base.gitlab-ci.yml
# - template: Jobs/SAST-IaC.gitlab-ci.yml # https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Jobs/SAST-IaC.gitlab-ci.yml
stages:
- build_workspace
- validate
- test
- build
- deploy
- cleanup
build_workspace:
stage: build_workspace
rules:
- if: $CREATE_TF_WORKSPACES
script:
- gitlab-terraform init
- gitlab-terraform workspace new dev
- gitlab-terraform workspace new test
- gitlab-terraform workspace new stage
- gitlab-terraform workspace new prod
validate_dev:
extends: .terraform:validate
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select dev
validate_test:
extends: .terraform:validate
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select test
validate_stage:
extends: .terraform:validate
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select stage
validate_prod:
extends: .terraform:validate
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select prod
build_dev:
extends: .terraform:build
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select dev
build_test:
extends: .terraform:build
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select test
build_stage:
extends: .terraform:build
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select stage
build_prod:
extends: .terraform:build
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select prod
deploy_dev:
extends: .terraform:deploy
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select dev
dependencies:
- build_dev
deploy_test:
extends: .terraform:deploy
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select test
dependencies:
- build_test
deploy_stage:
extends: .terraform:deploy
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select stage
dependencies:
- build_stage
deploy_prod:
extends: .terraform:deploy
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select prod
dependencies:
- build_prod
cleanup_dev:
extends: .terraform:destroy
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select dev
cleanup_test:
extends: .terraform:destroy
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select test
cleanup_stage:
extends: .terraform:destroy
before_script:
- gitlab-terraform init
- gitlab-terraform workspace select stage
cleanup_prod:
extends: .terraform:destroy
before_script:
- gitlab-terraform init
Compliance¶
The CCoE governance function may make spot checks to see if standards are being complied with.