Skip to main content

HCP Terraform Landing Zones

·2082 words·10 mins
Terraform Hashicorp Hcp

Using non-cloud terminology, a landing zone is:

… a “safe” area in which a helicopter or other type of vertical take-off device would land. They are mostly used during war. A landing zone has to be flat and should have a hard surface.

This specific definition of a landing zone was from the simple English version of Wikipedia - excellent for a non-native English speaker like myself!

This blog post discusses the cloud-related concept of landing zones. Specifically, we will learn about landing zones on HCP Terraform.

The concept of landing zones on HCP Terraform will be discussed conceptually with a few Terraform code blocks to illustrate how things are set up. Source code for the demo shown in this blog post is available on GitHub.

mattias-fjellstrom/hcp-terraform-landing-zones

Demo for how to set up HCP Terraform landing zones

HCL
0
0

What is HCP Terraform?
#

First things first: what is HCP Terraform?

If you think this is the first time you hear about HCP Terraform, chances are it’s not. Have you heard about Terraform Cloud? Until April 2024, HCP Terraform was known as Terraform Cloud.

HCP is short for HashiCorp Cloud Platform. HCP consists of SaaS (Software-as-a-Service) offerings of HashiCorp products. Among these products is Terraform, and it is offered under the name HCP Terraform. Technically, HCP Terraform is still an odd-player in the HCP portfolio. Terraform Cloud was HashiCorp’s first SaaS offering. Even if it is rebranded to HCP Terraform it still lives under its own domain. Eventually HCP Terraform might be fully integrated with the rest of HCP.

HCP Terraform provides an environment for collaboration and management of Terraform at scale. A few of the important features of HCP Terraform are:

  • State management
  • Policy-as-code integration with HashiCorp Sentinel and OPA
  • Run tasks to integrate third-party tools into the Terraform workflow
  • Workload identity integration with cloud platforms (e.g. AWS, Azure, GCP)
  • Terraform Stacks (currently in public preview)

What is a Landing Zone?
#

The landing zone concept is used on many different platforms.

Microsoft Azure discuss the landing zone concept in their Cloud Adoption Framework:

An Azure landing zone is an environment that follows key design principles across eight design areas. These design principles accommodate all application portfolios and enable application migration, modernization, and innovation at scale. An Azure landing zone uses subscriptions to isolate and scale application resources and platform resources. Subscriptions for application resources are called application landing zones, and subscriptions for platform resources are called platform landing zones.

AWS also has the concept of a landing zone, and it is described in the AWS Prescriptive Guidance:

A landing zone is a well-architected, multi-account AWS environment that is a starting point from which you can deploy workloads and applications. It provides a baseline to get started with multi-account architecture, identity and access management, governance, data security, network design, and logging.

Similarly, Google Cloud defines a landing zone in their Cloud Architecture Center:

Landing zones help your enterprise deploy, use, and scale Google Cloud services more securely. Landing zones are dynamic and grow as your enterprise adopts more cloud-based workloads over time. […] A landing zone spans multiple areas and includes different elements, such as identities, resource management, security, and networking.

Common to all the definitions above is that landing zones form the basis on which you will build the rest of your cloud environment on.

HashiCorp discuss landing zones in general terms in their Terraform: Operating Guide for Adoption:

A cloud landing zone is a foundational concept in cloud computing and a common deployment pattern for scaled customers. Defined as a standardized environment deployed in a cloud to facilitate secure, scalable, and efficient cloud operations, it forms a blueprint for setting up workloads in the cloud and serves as a launching pad for broader cloud adoption.

Further down in the document they go on to say:

Landing zones are commonly deployed by HCP Terraform, but the landing zone concept is also applicable to HCP Terraform by which a management workspace is deployed by the Platform Team during the onboarding of an internal customer using automation and which is then used to deploy the operational environment needed by that customer […]

Even if HCP Terraform is used to deploy landing zone architectures in AWS, Azure and GCP, you can also apply the landing zone concept to the resources in HCP Terraform itself.

HCP Terraform Landing Zone
#

What is part of a landing zone on HCP Terraform? This depends on what the rest of your cloud environment looks like. To be able to discuss something concrete in the rest of this blog post I will use a simple environment consisting of:

  • One HCP Terraform organization
  • One AWS account
  • One GitHub organization

An overview of what a landing zone could look like in this environment is shown in the following image.

HCP Terraform landing zone overview. Repositories on GitHub are connected to landing zone workspaces on HCP Terraform. Each landing zone workspace creates resources on HCP Terraform (a project and multiple workspaces) and sets up a connection to AWS

At a high level, the landing zone is set up through a HCP Terraform workspace connected to a specific GitHub repository that contains the code for the landing zone. The landing zone consists of a HCP Terraform project with a number of workspaces. Each workspace could in turn be connected to other GitHub repositories that could also be set up as part of the landing zone. Finally, the landing zone also has an OIDC connection to AWS so that each workspace in the project will be able to authenticate to AWS to create resources.

The discussion that follows can easily be extended to fit your specific environment. Implementing the differences will be more challenging, but in essence it is all about writing the required Terraform configurations.

In the discussion that follows I assume you are part of the platform team in your organization. The platform team manages HCP Terraform, AWS and GitHub environments. You have several internal developer teams in your organization. These teams are called your customers.

Request a New Landing Zone
#

A customer team is about to start working on a new internal application.

They sent a request for a new HCP Terraform landing zone. How this request process happens depends on what kind of self-service systems your organization is using. One example of a popular platform is ServiceNow, but it could also be self-service workflows on GitHub using automation with issues and GitHub Actions.

The customer team specifies two inputs in their request: business unit and application name. In this case it is the sales business unit and the application name is called forecast.

The request is approved, and this results in a new module block in the platform team Terraform configuration for landing zones. Again, the details of how this happens depends on what type of self-service platform you use.

module "sales_forecast" {
  source = "./modules/landing-zone"

  business_unit    = "sales"
  application_name = "forecast"

  github_organization        = var.github_organization
  aws_region                 = var.aws_region
  hcp_terraform_organization = var.hcp_terraform_organization
}

The platform team has created a module for HCP Terraform landing zones. In the example above the module is a local module, but it can also be published to your internal module registry in your HCP Terraform organization.

Create the Landing Zone
#

Once the module block is added to the platform team’s Terraform configuration the corresponding HCP Terraform workspace is triggered to create the landing zone.

First of all, a new GitHub repository is created for the customers landing zone (some arguments are omitted for brevity):

resource "github_repository" "default" {
  name        = "hcp-terraform-landing-zone-${var.business_unit}-${var.application_name}"
  visibility  = "private"

  gitignore_template = "Terraform"

  topics = [
    "hcp",
    "terraform",
    "landing-zone",
    var.business_unit,
    var.application_name,
  ]
}

This repository is populated with the boilerplate code for the landing zone stored in the directory landing-zone-repo:

locals {
  landing_zone_path       = "${path.module}/landing-zone-repo"
  landing_zone_repo_files = fileset(local.landing_zone_path, "**")
}

resource "github_repository_file" "landing_zone_files" {
  for_each = toset(local.landing_zone_repo_files)
  
  repository = github_repository.default.name
  file       = each.key
  content    = file("${local.landing_zone_path}/${each.key}")
}

Instead of having the Terraform files locally and uploading them to the new repository, you could instead have a dedicated repository that you use as a template repository. You would then configure the github_repository resource to use this template repository:

resource "github_repository" "default" {
  # other arguments omitted
  template {
    owner      = "your-github-organization"
    repository = "hcp-terraform-landing-zone-template"
  }
}

Note that if you use this approach, updating the landing zone source code will not be as straight-forward.

Another important part of the landing zone setup is the creation of a HCP Terraform workspace that deploys the landing zone for the customer team (some arguments are omitted for brevity):

resource "tfe_workspace" "landing_zone" {
  name        = "landing-zone-${var.business_unit}-${var.application_name}"
  project_id  = data.tfe_project.landing_zones.id

  vcs_repo {
    oauth_token_id = data.tfe_oauth_client.github.oauth_token_id
    branch         = "main"
    identifier     = "${var.github_organization}/${github_repository.default.name}"
  }
}

The workspace is connected to the GitHub repository that we created.

The last important piece created at this point is an AWS OIDC connection that all workspaces in the landing zone will use to authenticate API calls to AWS. The main part of this is the IAM role and its assume-role policy:

data "aws_iam_policy_document" "oidc_assume_role_policy" {
  statement {
    effect = "Allow"

    actions = ["sts:AssumeRoleWithWebIdentity"]

    principals {
      type        = "Federated"
      identifiers = [data.aws_iam_openid_connect_provider.hcp_terraform.arn]
    }

    condition {
      test     = "StringEquals"
      variable = "app.terraform.io:aud"
      values   = ["aws.workload.identity"]
    }

    condition {
      test     = "StringLike"
      variable = "app.terraform.io:sub"
      values = [
        join(":", [
          "organization",
          var.hcp_terraform_organization,
          "project",
          "${var.business_unit}-${var.application_name}",
          "*"
        ])
      ]
    }
  }
}

resource "aws_iam_role" "hcp_terraform_oidc" {
  name               = "hcp-terraform-oidc-${var.business_unit}-${var.application_name}"
  assume_role_policy = data.aws_iam_policy_document.oidc_assume_role_policy.json
}

This connection allows all workspaces in the landing zone project for the customer team.

Result
#

When the Terraform configuration has been applied the new landing zone workspace for the forecast application of the sales business unit has appeared in the list of workspaces.

The landing zone project contains one landing zone workspace

The new landing zone workspace will trigger automatically and create the landing zone for the customer team. Once it has completed you can see a new HCP Terraform project named sales-forecast.

List of projects in the HCP Terraform organization

Open the sales-forecast project to reveal a number of HCP Terraform workspaces that have been created as part of the landing zone.

A list of nine workspaces that have been set up as part of the landing zone

The design of the workspaces (or stacks) that are created as part of the landing zone will be unique for your context.

In this demo, each landing zone has one workspace for each layer (networking, identity and security) and each environment (dev, stage and prod). Each workspace is currently set up to use the CLI-driven workflow on HCP Terraform, but here you could also create specific GitHub repositories for each workspace and configure VCS-connections for all workspaces.

Scaling Up
#

Adding new landing zones means adding additional module blocks to the platform team’s Terraform configuration:

module "sales_forecast" {
  source = "./modules/landing-zone"

  business_unit    = "sales"
  application_name = "forecast"

  github_organization        = var.github_organization
  aws_region                 = var.aws_region
  hcp_terraform_organization = var.hcp_terraform_organization
}

# adding a new landing zone
module "new_business_supply_chain" {
  source = "./modules/landing-zone"

  business_unit    = "new-business"
  application_name = "supply-chain"

  github_organization        = var.github_organization
  aws_region                 = var.aws_region
  hcp_terraform_organization = var.hcp_terraform_organization
}

Applying the new Terraform configuration creates an additional landing zone workspace in the landing zones project.

A new landing zone is added for the new-business business unit

In this demo, new landing zones are added by adding more module blocks to a Terraform configuration.

A different approach is to use a HCP Terraform workspace for each landing zone. You could automate the setup of the workspace and connect it to a common GitHub repository and configure variables for the workspace to differentiate the workspaces from each other. Then you could apply updates to all landing zones by committing changes to this common GitHub repository.

There are many other options for how to do this, and you consider what is best for your specific context and environment. Perhaps you want to issue API-calls directly to HCP Terraform without the need to store the state?

Conclusions
#

The landing zone concept is a powerful tool to build a foundation for your cloud environments. Each hyperscaler (AWS, Azure, GCP and others) have their own definition of what a landing zone is and what is part of it.

On HCP Terraform, a landing zone can consist of a project with a number of workspaces and possible stacks (once they are generally available). The project can be configured with a variable set with authentication variables for all the workspaces. In the demo in this blog post each landing zone was configured with an AWS IAM role and associated OIDC provider connection, allowing the workspaces in the landing zone to create resources on AWS.

You can apply policies for all landing zones using policy sets on HCP Terraform to make sure all infrastructure created through the landing zones adhere to your organizational standards.

Even if the landing zone design described in this blog post does not fit your requirements, the general workflow of how to set this up should still be applicable for most contexts.

Mattias Fjellström
Author
Mattias Fjellström
Cloud architect · Author · HashiCorp Ambassador