Terraform
Analytical Platform's Core Infrastructure team offer a standardised pipeline for running Terraform. This is done via GitHub Actions and is available to all teams.
Terraform components are scanned by Checkov and tfsec
Terraform components are also linted by the Super Linter with fmt, tflint and terrascan
Style guide
Structure
-
data sources should be placed in
data.tf -
providers and versions should be placed in
terraform.tf -
variables should be placed in
variables.tf -
outputs should be placed in
outputs.tf -
resources should be grouped in files which are based from their name, e.g.
-
IAM policies should be placed in
iam-policies.tf -
IAM roles should be placed in
iam-roles.tf -
KMS keys should be placed in
kms-keys.tf
-
-
locals should be placed in
locals.tf -
modules should be placed in
modules/
Naming
-
resources should be named using snake case, e.g.
resource "aws_iam_role" "example_role_name" {} -
resources shouldn't contain what they are, e.g.
resource "aws_iam_role" "example_role_name" {}is preferred overresource "aws_iam_role" "example_role_name_role" {} -
modules should be named using snake case, e.g.
module "example_module_name" {} -
modules should be name relative to what they are doing, e.g.
module "example_iam_role" {}
Creating a new Terraform component
To create a new Terraform component, you will need to:
-
Create a directory in
terraform, e.g.terraform/aws/${AWS_ACCOUNT_NAME}/${COMPONENT} -
Using the table below for reference, create the required files in the component directory, replacing the placeholders with the correct values
Key Value Example AWS_ACCOUNT_NAMEName of the account as it appears inAWS IAM Identity Center analytical-platform-developmentAWS_ACCOUNT_IDID of the account as it appears inAWS IAM Identity Center 123456789012COMPONENTName of the component(We refer to a component as a collection of resources that create a service) eksENVIRONMENTName of the environment developmentIS_PRODUCTIONWhether the environment is production falsedata.tf(Example)data "aws_caller_identity" "session" { provider = aws.session } data "aws_iam_session_context" "session" { provider = aws.session arn = data.aws_caller_identity.session.arn }terraform.tf(Example)terraform { backend "s3" { acl = "private" bucket = "global-tf-state-aqsvzyd5u9" encrypt = true key = "aws/${AWS_ACCOUNT_NAME}/${COMPONENT}/terraform.tfstate" region = "eu-west-2" dynamodb_table = "global-tf-state-aqsvzyd5u9-locks" } required_providers { aws = { source = "hashicorp/aws" version = "${LATEST_VERSION}" # e.g. 5.9.0 can be found at https://registry.terraform.io/providers/hashicorp/aws/latest } } required_version = "~> 1.5" } provider "aws" { alias = "session" } provider "aws" { region = "eu-west-2" assume_role { role_arn = "arn:aws:iam::${var.account_ids["${AWS_ACCOUNT_NAME}"]}:role/GlobalGitHubActionAdmin" } default_tags { tags = var.tags } } provider "aws" { alias = "analytical-platform-management-production" region = "eu-west-2" assume_role { role_arn = can(regex("AdministratorAccess", data.aws_iam_session_context.session.issuer_arn)) ? null : "arn:aws:iam::${var.account_ids["analytical-platform-management-production"]}:role/GlobalGitHubActionAdmin" } default_tags { tags = var.tags } }terraform.tfvars(Example)account_ids = { ${AWS_ACCOUNT_NAME} = "${AWS_ACCOUNT_ID}" analytical-platform-management-production = "042130406152" } tags = { business-unit = "Platforms" application = "Data Platform" component = "${COMPONENT}" environment = "${ENVIRONMENT}" is-production = "${IS_PRODUCTION}" owner = "data-platform:data-platform-tech@digital.justice.gov.uk" infrastructure-support = "data-platform:data-platform-tech@digital.justice.gov.uk" source-code = "github.com/ministryofjustice/analytical-platform/terraform/aws/${AWS_ACCOUNT_NAME}/${COMPONENT}" }variables.tf(Example)variable "account_ids" { type = map(string) description = "Map of account names to account IDs" } variable "tags" { type = map(string) description = "Map of tags to apply to resources" } -
Generate a Terraform lock file by running the following command in the component's directory
terraform init -upgrade -backend=false -
Submit your changes using a pull request
Updating a Terraform component
-
Make the changes required to the component
-
Submit your changes using a pull request
Static Analysis
Static analysis was introduced in #866, however the components that make up Analytical Platform have not been remediated yet, this is addressed in #886
If you are working on a component that has not yet been addressed, you will need to add the label override-static-analysis to your pull request
This will allow the pull request to be merged without the static analysis checks failing
Was this page useful?