Wednesday, July 29, 2020

Terraform cloud region selection based on country

Here's a basic example of terraform code to automatically select a given cloud region based on a pre-configured mapping and the public IP of the machine running terraform. I will walk through the code pieces below:

The first piece of code sends a request to an internet accessible geoip provider. (I just picked one out there, there are many be aware of free restrictions if using in prod) This http request is made via the terraform http provider which then stores the JSON response given in data.http.geoipdata. You can pop open that URL in your browser to see the data it responds with.

# Grab current region info to use for auto choosing a region
data "http" "geoipdata" {
  url = "http://www.geoplugin.net/json.gp"

  # Optional request headers
  request_headers = {
    Accept = "application/json"
  }
}
Once we have gotten the response from that provider and it's told us which country we are in we can later use that to find a cloud region. We have a variable to control if this functionality is on or not and it's set to on by default

# Variable to enable auto region select
variable "enable_autoregion" {
  description = "If set to true, enable auto region choosing"
  type        = bool
  default     = true
}
We then build a map for which cloud region we will associate with which source IP's country. So for example, if the client is in Singapore (SG) or Malaysia (MY) then we want to use region "southeastasia" or for US clients, use "westus2"

# This maps country code to azure region
variable "regionmap" {
  type = map(string)
  default = {
    "SG" = "southeastasia"
    "MY" = "southeastasia"
    "US" = "westus2"
  }
}

Lastly, we bring it all together using a local value. Here we are saying, check if var.enable_region is true. If it is, then we take our response from data.http.geoipdata.body, decode it as jSON, grab the value it gave us for "geoplugin_countrycode", and then use that to match the value in our code above var.enable_autoregion. So the value returned/set for the local value for someone in "US" would be "westus2". Then at the end of the expression, if for some reason var.enable_autoregion is not set to true, then we will set local.localregion to "eastus" as a fallback.

# This matches the country code to to the map above to return the desired cloud region if the enable_autoregion var is true, otherwise defaults to eastus
locals {
localregion = var.enable_autoregion == true ? var.regionmap[(jsondecode(data.http.geoipdata.body)).geoplugin_countryCode] : "eastus"
}
So that can be then used in your code for the region, in a basic terraform-defined Azure RG, that looks like this:

# Set up terraform resource group
resource "azurerm_resource_group" "tfrg" {
        name = "yourrgname"
        location = local.localregion
}
Github code where I used this to stand up an azure instance is here.

No comments: