Introduction: Terraform with Azure

Tyler Wall
12 min readJan 20, 2024

Cloud Security NOW!, currently live on my website, covers the fundamentals of cloud computing and cloud security. It is filled with three hours of lectures at the front of the course that can be watched on any device including your phone, and even from your bed. Then you dive into a few labs with Serverless and Infrastructure as Code. Here is a short introduction to the course before we get started.

I hope you enjoy the following FULL introduction to Infrastructure as Code using Terraform with Azure.

Tyler Wall, MSc., CISSP, CCSK

The first thing we need to cover is what Infrastructure as Code actually is before it makes sense to dive into the lab.

Terraform is an immutable declarative approach. Immutable meaning when you want to make changes, the resources is replaced instead of updated. And declarative in that you just describe the end state and it figures out how to get there. Whereas an imperative approach you’re the one who needs to describe how to get there. Terraform is the most popular IaC language in the Enterprise world and a no brainer to use. You could become an expert at Terraform in 3–5 days. In just the next 20m, you’ll leave with the knowhow of what it does, when and how to use it.

With no further ado lets get you started with Terraform. The first thing you’re going to need to do is get Terraform installed. For the purposes of this article we’re going to be focusing on using a Mac, but the course does cover getting terraform installed on a Windows machine.

Now that was quick! Now lets dive into Terraform. For this exercise, the script and source code is all below the video. I recommend watching the video then scrolling down and working through the steps.

Assignment Notes

https://developer.hashicorp.com/terraform/tutorials/azure-get-started/azure-build
  • init — Init. Initialize the (local) Terraform environment. Usually executed only once per session.
  • plan — Plan. Compare the Terraform state with the as-is state in the cloud, build and display an execution plan. This does not change the deployment (read-only).
  • apply — Apply the plan from the plan phase. This potentially changes the deployment (read and write).
  • destroy — Destroy all resources that are governed by this specific terraform environment.

This article assumes that you have created an Azure account and subscription. The first thing we will do is install the Azure CLI tools and configure it to be used with terraform.

The Azure CLI Tool installed

Install the Azure CLI tool with brew:

brew update && brew install azure-cli

You will use the Azure CLI tool to authenticate with Azure. Terraform must authenticate to Azure to create infrastructure. In your terminal, use the Azure CLI tool to set up your account permissions locally.

az login

You now have logged in using your account you created in previous lectures. In the output in the terminal, find the ID of the subscription that you want to use:

{

"cloudName": "AzureCloud",
"homeTenantId": "0envbwi39-home-Tenant-Id",
"id": "35akss-subscription-id",
"isDefault": true,
"managedByTenants": [],
"name": "Subscription-Name",
"state": "Enabled",
"tenantId": "0envbwi39-TenantId",
"user": {
"name": "your-username@domain.com",
"type": "user"
}

Once you have chosen the account subscription ID, set the account with the Azure CLI.

az account set --subscription "35akss-subscription-id"

Next, we create a Service Principal. A Service Principal is an application within Azure Active Directory with the authentication tokens Terraform needs to perform actions on your behalf. Update the <SUBSCRIPTION_ID> with the subscription ID you specified in the previous step.

az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/<SUBSCRIPTION_ID>"clear

The output includes credentials that you must protect. Be sure that you do not include these credentials in your code or check the credentials into your source control. For more information, see the assignment details

{
"appId": "xxxxxx-xxx-xxxx-xxxx-xxxxxxxxxx",
"displayName": "azure-cli-2022-xxxx",
"password": "xxxxxx~xxxxxx~xxxxx",
"tenant": "xxxxx-xxxx-xxxxx-xxxx-xxxxx"
}

Next you need to set your environment variables. HashiCorp recommends setting these values as environment variables rather than saving them in your Terraform configuration. Open a terminal and input the values that were outputted from the previous command:

 export ARM_CLIENT_ID="<APPID_VALUE>"
export ARM_CLIENT_SECRET="<PASSWORD_VALUE>"
export ARM_SUBSCRIPTION_ID="<SUBSCRIPTION_ID>"
export ARM_TENANT_ID="<TENANT_VALUE>"

Install Visual Studio Code and Setup Environment

Great! We are all configured to use Azure now. Now the next thing we are going to do is open up a terminal install Visual Studio Code by issuing this command:

brew install visual-studio-code

Next, in the terminal we will issue the following commands to create a directory that will contain our Terraform configuration:

mkdir ~/tf-exercise-1
cd ~/tf-exercise-1

And open up a file for main.tf

code main.tf

Now we need to write configuration to create a new resource group. See the assignment detail to copy and paste the code snippet.



# Configure the Azure provider
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.0.2"
}
}


required_version = ">= 1.1.0"
}


provider "azurerm" {
features {}
}


resource "azurerm_resource_group" "rg" {
name = "myTFResourceGroup"
location = "westus2"
}

Note

The location of your resource group is hardcoded in this example. If you do not have access to the resource group location westus2, update the main.tf file with your Azure region. This is a complete configuration that Terraform can apply. In the following sections we will review each block of the configuration in more detail.

Terraform Block

The terraform {} block contains Terraform settings, including the required providers Terraform will use to provision your infrastructure. For each provider, the source attribute defines an optional hostname, a namespace, and the provider type. Terraform installs providers from the Terraform Registry by default. In this example configuration, the azurerm provider’s source is defined as hashicorp/azurerm, which is shorthand for registry.terraform.io/hashicorp/azurerm.

You can also define a version constraint for each provider in the required_providers block. The version attribute is optional, but we recommend using it to enforce the provider version. Without it, Terraform will always use the latest version of the provider, which may introduce breaking changes.

Providers

The provider block configures the specified provider, in this case azurerm. A provider is a plugin that Terraform uses to create and manage your resources. You can define multiple provider blocks in a Terraform configuration to manage resources from different providers.

Resource

Use resource blocks to define components of your infrastructure. A resource might be a physical component such as a server, or it can be a logical resource such as a Heroku application.

Resource blocks have two strings before the block: the resource type and the resource name. In this example, the resource type is azurerm_resource_group and the name is rg. The prefix of the type maps to the name of the provider. In the example configuration, Terraform manages the azurerm_resource_group resource with the azurerm provider. Together, the resource type and resource name form a unique ID for the resource. For example, the ID for your network is azurerm_resource_group.rg.

Resource blocks contain arguments which you use to configure the resource. The Azure provider documentation documents supported resources and their configuration options, including azurerm_resource_group and its supported arguments.

Initialize your Terraform configuration

Initialize your learn-terraform-azure directory in your terminal. The terraform commands will work with any operating system. Your output should look similar to the one in the assignment text.

terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/azurerm versions matching "~> 3.0.2"...
- Installing hashicorp/azurerm v3.0.2...
- Installed hashicorp/azurerm v3.0.2 (signed by HashiCorp)
Terraform has been successfully initialized!

You may now begin working with Terraform. Try running “terraform plan” to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary.

Format and validate the configuration

We recommend using consistent formatting in all of your configuration files. The terraform fmt command automatically updates configurations in the current directory for readability and consistency.

Format your configuration. Terraform will print out the names of the files it modified, if any. In this case, your configuration file was already formatted correctly, so Terraform won’t return any file names.

terraform fmt

You can also make sure your configuration is syntactically valid and internally consistent by using the terraform validate command. The example configuration provided above is valid, so Terraform will return a success message.

terraform validate

Success! The configuration is valid.

Apply your Terraform Configuration

Run the terraform apply command to apply your configuration. This output shows the execution plan and will prompt you for approval before proceeding. If anything in the plan seems incorrect or dangerous, it is safe to abort here with no changes made to your infrastructure. Type yes at the confirmation prompt to proceed.

terraform apply

An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols:

+ create

Terraform will perform the action of creating a resource group:

azurerm_resource_group.rg will be created

+ resource "azurerm_resource_group" "rg" {
+ id = (known after apply)
+ location = "westus2"
+ name = "myTFResourceGroup"
}

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?

Terraform will perform the actions described above.


Only 'yes' will be accepted to approve.

Enter a value: yes

azurerm_resource_group.rg: Creating...
azurerm_resource_group.rg: Creation complete after 1s [id=/subscriptions/c9ed8610-47a3-4107-a2b2-a322114dfb29/resourceGroups/myTFResourceGroup]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Navigate to the Azure portal in your web browser to check to make sure the resource group was created.

Inspect your state

When you apply your configuration, Terraform writes data into a file called terraform.tfstate. This file contains the IDs and properties of the resources Terraform created so that it can manage or destroy those resources going forward. Your state file contains all of the data in your configuration and could also contain sensitive values in plaintext, so do not share it or check it in to source control.

For teams or larger projects, consider storing your state remotely. Remote stage storage enables collaboration using Terraform but is beyond the scope of this exercise.

Inspect the current state using terraform show.

terraform show
 azurerm_resource_group.rg:
 resource "azurerm_resource_group" "rg" {
    id       = "/subscriptions/c9ed8610-47a3-4107-a2b2-   a322114dfb29/resourceGroups/myTFResourceGroup"
    location = "westus2"
    name     = "myTFResourceGroup"
}

When Terraform created this resource group, it also gathered the resource’s properties and meta-data. These values can be referenced to configure other resources or outputs.

To review the information in your state file, use the state command. If you have a long state file, you can see a list of the resources you created with Terraform by using the list subcommand.

terraform state list
azurerm_resource_group.rg

If you run terraform state, you will see a full list of available commands to view and manipulate the configuration’s state.

terraform state

Usage: terraform state <subcommand> [options] [args]

This command has subcommands for advanced state management. These subcommands can be used to slice and dice the Terraform state. This is sometimes necessary in advanced cases. For your safety, all state management commands that modify the state create a timestamped backup of the state prior to making modifications.

The structure and output of the commands is specifically tailored to work well with the common Unix utilities such as grep, awk, etc. We recommend using those tools to perform more advanced state tasks.

Terraform Destroy

Lastly, issue the terraform destroy command to complete the lifecycle and undo the changes that you made. Terraform keeps a state of the changes you made in the terraform state file so it knows exactly which ones to undo.

terraform destroy
Terraform will perform the following actions:
  # azurerm_resource_group.rg will be destroyed
  - resource "azurerm_resource_group" "rg" {
      - id       = "/subscriptions/b7b18fdb-6e24-4934-a25e-2957c9e62d05/resourceGroups/myTFResourceGroup" -> null
      - location = "westus2" -> null
      - name     = "myTFResourceGroup" -> null
      - tags     = {} -> null
    }
Plan: 0 to add, 0 to change, 1 to destroy.
Do you really want to destroy all resources?

Quiz: What is this block called and is it in every Terraform file?

And that completes the lifecycle of initializing, planning, applying and destroying AWS infrastructure with Terraform. As of now, you understand how the Terraform lifecycle works and have configured both Azure and AWS with Terraform so that you can continue your learning. If you would like to continue your learning with Terraform, I’d highly recommend the Udemy course Terraform for Absolute Beginners with Labs. This innovative course from KodeKloud walks you through creating a Terraform file from scratch with lectures and by using their proprietary lab platform KodeKloud. The only reason I recommend it is because I took it myself and thought it was a fantastic course.

Wrapping Up

After taking the course from KodeKloud, I scored a 60% on the Hashicorp Terraform Associate certification. 70% is required to pass the exam. There are some things the course doesn’t cover about Terraform Cloud and Hashicorp Vault that really got me. I grabbed some practice tests from Udemy and I’ll be retaking the certification soon. So far I’m scoring 80% in the practice tests.

I passed!

Theres much more to learn in Cloud Security NOW!

This course WILL:

  • Teach you the fundamentals of Cloud in general and Cloud Security including a deep dive into the Cloud Security Models (IaaS, PaaS, SaaS) and Cloud Deployment Models (Public, Private, Community, Hybrid, Multi)
  • Teach you about the Cloud Service Providers (AWS, Azure, GCP, Alibaba, IBM..etc), their popularity ranked and strengths.
  • Teach you about the various tooling you’ll need to be familiar with (CWPP, CSPM, CIEM, CASB, CSPM, SSO)
  • Teach you about what cybersecurity risks are inherent and specific to the Cloud (Lack of Cloud Security Skills, Misconfigurations, Increased Attack Surface, Lack of Focus on Identity, Lack of Standardization and Visibility, Data Leakage, Data Privacy/Sovereignty, Incident Response)
  • Show you the different cloud security career paths that are present and which one is the easiest for you to transition into (Cloud Security Engineer/Architect/Manager)
  • Teach you about the biggest certifications and their strengths and weaknesses with strategy on how to pass them (CCSK, CCSP, AWS Certified Specialty — Security, Azure Security Engineer, Google Cloud Security Engineer)
  • Guide you on getting that valuable multi-cloud security experience without having an enterprise environment to practice
  • Get you hands-on with Terraform and Serverless functions in both AWS and Azure.
  • Get you hands-on with checking Infrastructure as Code (IaC) for misconfigurations with an open source static code analysis tool (Checkov).

Enroll in Cloud Security NOW!

More articles in this series:

Tyler Wall is the founder of Cyber NOW Education. He holds bills for a Master of Science from Purdue University, and also CISSP, CCSK, CFSR, CEH, Sec+, Net+, A+ certifications. He mastered the SOC after having held every position from analyst to architect and is the author of three books, 100+ professional articles, four online courses, and regularly holds webinars for new cybersecurity talent.

You can connect with him on LinkedIn.

Get 20% off all courses in our On-Demand catalog with coupon code “Welcome20”

Download the Azure Security Labs eBook from the Secure Style Store. These labs walk you through several hands-on fun labs in Microsoft Azure, leaving you with the know-how to create a gig in Fiverr or Upwork to start your cybersecurity freelancing.

Also available in the Secure Style Store, download the Job Hunting Application Tracker for FREE to keep track of all your job applications.

Check out my latest book Jump-start Your SOC Analyst Career: A Roadmap to Cybersecurity Success published June 1st, 2024 and winner of the 2024 Cybersecurity Excellence Awards.

--

--

Tyler Wall
Tyler Wall

Written by Tyler Wall

Founder of Cyber NOW Education | Husband & Father | Published Author | Instructor | Master Mason | 3D Printing & Modeling | Astrophotography

Responses (1)