Skip to main content
Jorge Bernhardt Jorge Bernhardt
  1. Posts/

Terraform - Deploying Azure Resource Locks

·1144 words·6 mins· 100 views · 5 likes ·
Terraform Microsoft Azure Azure Resource Locks IaC

Hi! Did you know that Azure Resource Locks can provide an extra layer of protection for your resources in case of accidental changes or deletions? And best of all, we can deploy them using Terraform.

By automating the process, you can apply locks at different levels of your infrastructure, whether it’s your entire subscription, specific resource groups, or even individual resources. This means that your resources are more secure, and you can be sure that their integrity and stability will not be compromised.

In this post, I’ll walk you through the process step by step so you can easily implement Azure Resource Locks using Terraform. By the end, you’ll have a solid understanding of how you can use Terraform to deploy and protect your critical Azure resources using Azure resource locks.


Prerequisites #

  • You need Terraform CLI on your local machine, if you’re new to using Terraform to deploy Microsoft Azure resources, then I recommend you check out this link.
  • A text editor or IDE of your choice (Visual Studio Code with Terraform extension is my recommendation)
Declare Azure Provider in Terraform>

Declare Azure Provider in Terraform #

The file in Terraform is used to specify and configure the providers used in your Terraform configuration. A provider is a service or platform where the resources will be managed. This could be a cloud provider like Microsoft Azure, AWS, Google Cloud, etc.

This file is important because it tells Terraform which provider’s API to use when creating, updating, and deleting resources. Without it, Terraform wouldn’t know where to manage your resources.

provider "azurerm" {
  features {}
Create Azure resource locks using Terraform>

Create Azure resource locks using Terraform #

In the case of Azure resource locks deployment, the file contains the following key components:

  • azurerm_subscription :This block retrieves information about the current Azure subscription that is in use. In this case, it is used to construct the scope for each resource lock.
  • azurerm_management_lock :This block creates a series of resource locks in Azure. for_each allows you to iterate over the input values defined in var.lock_info. For each item, creates a lock with the specified name, lock level, notes, and scope. The scope is determined through conditional logic that attempts to generate a string that specifies a path to a specific resource. If it cannot generate that string (for example, because the resource group, resource type, or resource name are not defined), it will try to generate a string that specifies a resource group. If that’s not possible either, it will use the current subscription ID as the lock scope. This logic allows this block of code to be used to create locks at the resource, resource group, or subscription level, based on the data provided in var.lock_info.
// Get the current Azure subscription details
data "azurerm_subscription" "current" {

// Looping over the input map to create management locks
resource "azurerm_management_lock" "locks" {
  for_each = { for k, v in var.lock_info : v.index => v }

  name       =
  lock_level = each.value.lock_level // The lock level - CanNotDelete or ReadOnly
  notes      = each.value.notes

  scope = try("subscriptions/${data.azurerm_subscription.current.subscription_id}/resourceGroups/${each.value.resource_group_name}/providers/${each.value.resource_type}/${each.value.resource_name}",

Important: The use of v.index in the for_each statement ensures that the azurerm_management_lock resources are created in a particular order based on the index value. In the context of Azure Resource Locks, the order of creation is important as Azure applies the most restrictive lock in the hierarchy. If you have a lock at the subscription level, it will prevent you from making modifications at the resource or resource group level within that subscription.

Declaration of input variables>

Declaration of input variables #

The file in Terraform defines the variables I will use in the file. These variables allow for more flexibility and reusability in the code. In this example, the variables are defined in the include:

  • lock_info : This block defines a variable called lock_info, a map where each value is an object with properties like index, name, lock_level, notes, resource_group_name, resource_type, and resource_name.
// Declares a variable "lock_info" that will be used to create resource locks
variable "lock_info" {
  description = "Information for creating resource locks"
  type = map(object({
    index               = string // An index identifier as a string
    name                = string
    lock_level          = string // The lock level - CanNotDelete or ReadOnly
    notes               = string
    resource_group_name = optional(string)
    resource_type       = optional(string)
    resource_name       = optional(string)

Important: The index value controls the order in which locks are created so that you can ensure that locks are applied to lower-level resources first (such as individual resources) before locks are applied to higher-level resources (such as resource groups or the entire subscription). In this way, you can avoid situations where a higher-level lock could prevent the creation of a lower-level lock.

Declaration of output values>

Declaration of output values #

The file in Terraform extracts and displays information about the resources created or managed by your Terraform configuration. These outputs are defined using the output keyword and can be used to return information that can be useful for the user, for other Terraform configurations, or for programmatically using the information in scripts or other tools.

In this example, the file returns information about the resource locks that were created.

Once Terraform has finished applying your configuration, it will display the defined outputs.

// Outputs the created resource locks
output "created_locks" {
  description = "The created resource locks"
  value       = azurerm_management_lock.locks
Executing the Terraform Deployment>

Executing the Terraform Deployment #

Now that you’ve declared the resources correctly, it’s time to take the following steps to deploy them in your Azure environment.

  • Initialization: To begin, execute the terraform init command. This will initialize your working directory that holds the .tf files and download the provider specified in the file, and configure the Terraform backend. I suggest looking at this link if you’re curious about the process.

  • Planning: Next, execute the terraform plan. This command creates an execution plan and shows Terraform’s actions to achieve the desired state defined in your .tf files. This gives you a chance to review the changes before applying them.

  • Apply: When you’re satisfied with the plan, execute the terraform apply command. This will implement the required modifications to attain the intended infrastructure state. Before making any changes, you will be asked to confirm your decision.

  • Inspection: After applying the changes, you can use terraform show command to see the current state of your infrastructure.

  • Destroy (optional): when a project is no longer needed or when resources have become outdated. You can use the terraform destroy command. This will remove all the resources that Terraform has created.

References and useful links #

Thank you for taking the time to read my post. I sincerely hope that you find it helpful.