Skip to main content

ALZ Engineering practices

This page lists the current ALZ practices and ways of working from an engineering perspective, including choices on tooling/languages.

Source Control

We use Github for source control.

Repositories

We use the following repositories:

ministryofjustice/azure-landing-zone 
ministryofjustice/azure-landing-zone-user-guides
ministryofjustice/staff-infrastructure-azure-landing-zone
ministryofjustice/staff-infrastructure-azure-landing-zone-scripts
ministryofjustice/staff-infrastructure-azure-landing-zone-aad
ministryofjustice/staff-infrastructure-alz-monitor-alerts
ministryofjustice/staff-infrastructure-alz-ci-templates
ministryofjustice/staff-infrastructure-alz-terraform-policy
ministryofjustice/staff-infrastructure-alz-terraform-vm
ministryofjustice/staff-infrastructure-alz-patching
ministryofjustice/staff-infrastructure-alz-backup
ministryofjustice/staff-infrastructure-alz-terraform-vnet
ministryofjustice/staff-infrastructure-alz-github-mgmt

Branching Strategy

We have a single branch: main and any features/changes/bug fixes are done on a feature branch which is merged back into main via Pull Request.

main is the deployment branch for all environments.

Repository Configuration

We currently require a single reviewer per pull request and we feel this is a good compromise between speed and code quality.

Rebase and Squash Merge are allowed but straight merge is not as this can result in a very messy history.

We’re currently trialling the use of Terraform for our repository configuration - Terraform Github provider. The code for which can be found in ministryofjustice/staff-infrastructure-alz-github-mgmt. This is deployed using Azure Devops as normal.

We’re also making use of Dependabot in some repositories to manage our Terraform and provider versions. This is configured in the usual place: .github/dependabot.yml which can be checked for repo specific schedules etc…

Naming Convention for Feature Branches

The suggested naming convention is as follows:

<JIRA_ISSUE_NUMBER>-TaskName

e.g.

hc-606-create-custom-policy

Small ad-hoc fixes do not have to strictly follow the above but should have a sensible name.

Pull Requests Process

Once your code is ready to review:

  • Create a PR in Github
  • Ensure that there is a good description
  • Ensure that all checks have passed.

Try and only open Pull requests for code that is almost ready to be merged, not as a means to trigger pipelines for testing. Some troubleshooting from the results of failed Pull Request pipeline checks is going to happen at times and is fine, PR’s shouldn’t be the primary way this is done, however.

Walkthrough (over the shoulder review)

It is sometimes useful to walk a reviewer through the code to explain the changes. This is specially useful if the reviewer is not very familiar with the code being reviewed or the PR contains complicated, idiosyncratic or unexpected/surprising code.

As a reviewer you should feel free to ask for a walkthrough at any time for any reason, it is a good tool to spread the knowledge and can also help the author of the PR detect issues.

Require conversation resolution before merging

We have this setting enabled, which means that all review conversations will need to be closed before merging is allowed.

PR Review Order

It is recommended that PRs are reviewed in the order that they are raised to ensure that when they are applied the plan displayed in the PR is as close as possible as to the actual plan.

For example if PR 1 and PR 3 touch the same bits of code but PR 3 is applied before PR 1 then this might create issues.

Static Analysis

We currently use Checkov for static analysis of our terraform code, this is currently embedded in our standard deployment template. (Further tooling for linting is planned as future work using Github Actions.)

Finally, a GitHub action, code-formatter, will run terraform fmt and commit any changed code back into the branch on PR.

Preferred Technologies

We currently use the following technologies, if you want to use a different technology, e.g. terratest for testing, please discuss it with the whole team before doing any work.

Area Technology
CI/CD Azure Pipelines
IaC Terraform
General Scripting Powershell
Automated Testing Pester

Resource Tagging Process

The ALZ team follows a strict resource tagging process to ensure consistency and compliance across all resources. Tags are applied at the resource group level via Terraform and automatically inherited by the resources using Azure policies.

Key Tags Applied

We enforce the following tags across all resource groups:

  • Application: Specifies the application to which the resources belong.
  • BusinessUnit: Identifies the business unit responsible for the resource.
  • IsProduction: Indicates whether the resource is for production or non-production environments.
  • Owner: Identifies the resource owner.
  • PurchaseOrder: Tracks the purchase order associated with the resource.
  • Source-Code: Refers to the source code related to the resource.

Access Required for Tagging

All resources and resource groups are created via Terraform, and tagging is managed exclusively through Terraform code. This ensures consistency across environments, and we aim to maintain this practice without manual intervention in the Azure portal.

Applying Tags via Azure Policy

Tags are applied to resource groups only. Tags are not directly applied to resources but are inherited by resources through Azure policies. These policies are responsible for pushing the specific tags down to resources. Exemptions may exist, and non-compliant resources should be reviewed for applicable exemptions before remediation.

Monitoring and Compliance

Azure Policy is used to monitor compliance with the tagging process. Notifications for non-compliant resources are recommended but not yet implemented. Remediation actions should be run for flagged resources after policy evaluation to ensure compliance.

In some cases, during a Terraform pipeline run, you may encounter errors where it shows that the tags for a resource are being set to null. This issue typically occurs when the resource block in Terraform does not have tags explicitly defined.

To resolve this issue, it is recommended to use the lifecycle block with the ignore_changes argument in the resource definition. This will instruct Terraform to ignore the tags being applied through Azure policy inheritance, preventing Terraform from attempting to overwrite or remove these tags. Here’s an example of how to implement this:

resource "azurerm_storage_account" "example" {
  name                     = "examplestorageacct"
  resource_group_name       = azurerm_resource_group.example.name
  location                  = azurerm_resource_group.example.location
  account_tier              = "Standard"
  account_replication_type  = "LRS"

  lifecycle {
    ignore_changes = [
      tags,
    ]
  }
}

This approach ensures that Terraform will not attempt to modify or remove tags inherited from the resource group through Azure policy.

Special Cases for Different Tags

In rare cases where a resource needs to have a tag that differs from its parent resource group for an approved reason, it is recommended to add a lifecycle ignore block for the inherited tags on that specific resource. This prevents Terraform from overwriting any tags that need to be customized.

By implementing this solution, you can avoid pipeline errors related to tag nullification and ensure that Terraform only manages the tags it explicitly sets, while respecting those applied via policy inheritance.

This page was last reviewed on 15 October 2024. It needs to be reviewed again on 15 January 2025 .
This page was set to be reviewed before 15 January 2025. This might mean the content is out of date.