MutantMahesh's Blog

Seeking to know.

Apr 22, 2021 - 2 minute read - Terraform Hashicorp DevOps

Terraform reference dependy resource value in dependent resource

Requirement

  1. I was having a requirement of migrating all the configuration from one cloudflare domain (being used in production) to another cloudflare domain in another account.
  2. I found one interesting tool called cf-terraforming . This tool allows you to generate the terraform code for existing domain configuration.
  3. There are certain limit though, this tools is not able to generate terraform code for every possible resource in cloudflare. The list of supported resources is mentioned on above link.
  4. After generating the terraform code for one domain, you can do the terraform init then terraform plan -out=plan-file to generate the plan and apply that plan with terraform apply plan-file to another cloudflare account by using the correct zone_id of the target cloudflare account.
  5. Problem: When creating resources of cloudflare_firewall_rule type I had the dependency on cloudflare_filter type resource. Until the cloudflare_filter type resource is created I can not reference that resource’s ID in cloudflare_firewall_rule resource.

Setup

versions.tf file

terraform {
  required_version = ">= v0.15.0"
  required_providers {
    cloudflare = {
      source  = "cloudflare/cloudflare"
      version = ">= 2.20.0"
    }
  }
}

provider.tf file

provider "cloudflare" {
  email = var.cf_email
  api_key = var.cf_api_key
}

variables.tf file

variable "zone_id" {
  default     = ""
  description = "The cloudflare zone id. This is a sensitive information and should not be stored in version control. This should be overridden by tf at the runtime."
}

variable "domain" {
  default     = "www.crohnscolitisfoundation.org"
  description = "The is domain name of cloudflare. This should be overridden by tf at the runtime."
}

variable "cf_email" {
  type        = string
  default     = ""
  description = "This should be overriden by tf at the runtime."
}

variable "cf_api_key" {
  type        = string
  default     = "secure-api-key"
  description = "This is sensitive information. This should not be stored in version control. This should be overridden by tf at the runtime."
}

Solution: Reference the cloudflare_filter resource id dynamically in cloudflare_firewall_rule resource definition.

filter.tf file:

resource "cloudflare_filter" "terraform_managed_resource_090fbfccd80a4797bdcc83f398e188d0" {
  expression = "(http.request.uri.path matches \"/wp-(admin|includes|json)/\")"
  paused = false
  zone_id = var.zone_id
  description = "Wordpress common folders (excluding content)"
}

firewall_rule.tf file

resource "cloudflare_firewall_rule" "terraform_managed_resource_81ce9586786f4ae88d31b5abe406fbe7" {
  action = "block"
  description = "Wordpress common folders (excluding content)"
  filter_id = cloudflare_filter.terraform_managed_resource_090fbfccd80a4797bdcc83f398e188d0.id
  paused = false
  zone_id = var.zone_id
}

The thing to notice in cloudflare_firewall_rule definition is filter_id = cloudflare_filter.terraform_managed_resource_090fbfccd80a4797bdcc83f398e188d0.id dynamically being referenced. The terraform will take care of creating the cloudflare_filter first and then referencing its ID in cloudflare_firewall_rule.

PS

terraform.tfvars file

zone_id = "<your target zone_id>"
domain = "<your target domain>"
cf_email = "<email id>"
cf_api_key = "<Cloudflre api key>"