This is going to be a multipart post because it involves quite a lot of integrations. Each post will focus on a specific bit of the overall task. It will focus on an imaginary project named the Unicorn project. I’m going to cover:

So, let’s get started. 🙂

Unicorn Architecture

Let’s start with a high level description of the Unicorn service.

Here is what the architecture of the Unicorn service will look like. The Unicorn service is a very small service. The API supports a single verb, GET, and returns a single GUID when called. The Unicorn dev team is very small but has big plans to expand the API to return other things like random character strings and random numbers.

I’m going to do something a little strange here. I’m going to describe the architecture of the individual environments from right to left because I believe it will be easier to understand. The flow of information actually goes from left to right, but the complexity increases as we move from right to left. So I’m going to explain the easy stuff first and as we move to the left across the diagram, the complexity will increase.

Starting on the right, there is a very simple Unicorn REST API hosted in an Azure App Service. An Azure Key Vault is provisioned to the resource group to keep sensitive configuration values like API keys from being exposed. This is the production environment.

Moving to the left, there is a Resource Group that holds resources that aren’t directly a part of the Unicorn service. These include a Storage Account to store the Terraform state file and Azure Monitor resources.

The Terraform state file is accessed by an Azure security principal that has limited rights to create Azure resources. It authenticates to Azure using OAuth2. The security principal, after logging in to Azure. will compare the infrastructure defined in the unicorn.tf file to the unicorn.tfstate file in the Storage Account. If they don’t match, Terraform it will create a plan to change the resources in Azure to match the unicorn.tf file. Then it will do what is necessary to update the Azure resources.

Terraform is run by the GitHub Action, which besides running the Terraform tasks, builds the source code and deploys it to the production environment

Terraform Template

I’m going to start with a bare bones Terraform template that has it’s state file stored in an Azure Storage Account.

What’s going on here? First, the top level “terraform” block configures Terraform itself. Within the “terraform” definition, the required_version is saying that the version of the Terraform client needs to be greater than version 1.2,

In the required_providers section, we are declaring that a provider with the local name “azurerm” will use the “hashicorp/azurerm” module and the version of that must be about 3.7.0. azurerm is the provider that allows connecting to and configuring resources in Azure. A comprehensive list of providers can be found in the Hashicorp documentation site.

The “backend” statement configures the provider with the local name “azurerm”. This is where we are defining where the Terraform state file will be created and maintained. Here we are defining that the state file will be located in a resource group named “rg-unicorn-platform”, in a storage account named “staunicornplatform” and in a blob container named “tfstate”. The key defines the actual name of the state file withing the blob container.

Finally, outside of the “terraform” block, we are defining that the provider with the local name “azurerm” doesn’t yet have any features. This is simply a placeholder that will be fleshed out more in a future version of the template.

I keep all of my projects in a folder named “Source”, so I create a folder for the unicorn project in .\Source, change to that directory and fire up my favorite editor.

In VSCode, I create a file named unicorn.tf and paste the text of the template from above into the file and save it.

In this post, I described the high-level architecture of the to-be system. I also covered creating a bare-bones Terraform template that would store it’s state file in an Azure Storage Account. In my next post, I’ll cover creating the actual resource group, storage account and blob storage. Then I’ll create the actual state file in the storage account.

Next: Creating the Terraform State File in Azure