Skip to content

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:

  1. Structuring terraform repositories.
  2. Use of modules within in terraform.
  3. Use of terraform workspaces to manage deployments across different environments.
  4. Backend file creation.
  5. Provider file usage.
  6. 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:

  1. 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.

VDPS terraform

  1. 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

  1. Platform Engineers should use modules from Terraform AWS Modules (https://registry.terraform.io/namespaces/terraform-aws-modules) wherever possible rather than creating individual resources.
  2. Module versions should be hard coded to avoid issues with module changes at later dates.
  3. Platform Engineers should avoid creating their own module structures.

User of terraform workspaces to manage deployments across different environments

  1. The standard NHS BSA terraform Gitlab pipeline file utilises terraform workspaces. This is explained further in the Pipeline files section of this page.
  2. 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

  1. 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

  1. 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

  1. 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.