AzApi provider in Terraform

AzApi provider in Terraform

There was a requirement once, to set up a time based retention policy with its scope on Azure storage container. Those who have worked on Azure or have a brief idea about storage in Azure, might know about the time-based retention policy. I had already created a terraform script to set up a storage account in azure, so I thought of editing the same terraform file to initiate this policy while creation of storage account and storage container.

While working on it's implementation, I found that managing retention policies on storage containers is not yet supported by azurerm_storage_container. Looking to implement it one way or the other in terraform, I came across AzAPI.

What is AzAPI Provider?

Terraform AzAPI provider works in bridging the gap which exists in the Terraform AzureRM provider (and the Go SDK for Azure). It is a very thin layer on top of the Azure ARM REST APIs. It is used to authenticate to and manage Azure resources and functionality using the Azure Resource Manager APIs directly.

It enables the capability to manage Azure resources that are not yet or may never be supported in AzureRM provider. This provider and resources are fully compatible with Terraform. This compatibility ensures that you get all the benefits of Terraform that you rely on.

Two generic resources are included in the provider

  1. azapi_resource : It enables the management of any ARM resource that supports the usage of CRUD (Create, Read, Update and Delete)

  2. azapi_update_resource : It is used to manage resources or parts of resources that do not have full CRUD. It works only with the read and update operation.

Our Use Case

In our case, we need to update the property on the existing resource. The property or policy of time-based retention needs to be set up on the storage container. So here, azapi_update_resource will be used.

The requirement was to set up immutabilitypolicy as well as setting immutabilityPeriodSinceCreationInDays to 30 days since we want the retention upto 30 days. All these values are not exposed via the AzureARM, so azapi_update_resource is used to configure all the properties as per the requirement. Below is the terraform script performing the same:

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "=3.7.0"
    }
    azapi = {
      source  = "azure/azapi"
      version = ">=0.1.1"
    }
  }
}

provider "azurerm" {
  features {}
  skip_provider_registration = true
}

provider "azapi" {
  skip_provider_registration = true
}

resource "azurerm_resource_group" "this" {
  name     = var.resource_group_name
  location = var.location
}

resource "azurerm_storage_account" "this" {
  name                     = var.storage_account
  resource_group_name      = azurerm_resource_group.this.name
  location                 = azurerm_resource_group.this.location
  account_tier             = "Standard"
  account_replication_type = "LRS"

}

resource "azurerm_storage_container" "this" {
  name                  = var.storage_container
  storage_account_name  = azurerm_storage_account.this.name
  container_access_type = "private"
}


resource "azapi_update_resource" "this" {
  type      = "Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies@2021-08-01"
  name      = "default"
  parent_id = azurerm_storage_container.this.resource_manager_id

  body = jsonencode({
    properties = {
      allowProtectedAppendWrites            = false
      # allowProtectedAppendWritesAll         = null
      immutabilityPeriodSinceCreationInDays = 30
    }
  })
  response_export_values = ["etag"]
}

In the above mentioned terraform script, we can notice that azapi is mentioned under the providers since it would be used.

azurerm provider is used to create the different resources as per the requirement, namely a resource group, storage account and a storage container.

azapi is used since it would be helpful to set up the policy since azurerm alone is not sufficient to do the same. The azure template for storage along with api version is passed under 'type' and the template format for the same is passed under 'body'. This is different to AzureRM

type - It contains the resource type and the api version, following the convention: @ as an example Microsoft.Storage/storageAccounts/blobServices/containers/immutabilityPolicies@2021-08-01

parent_id - Id of the resource or the item deployed. As an example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-test

body - Is the JSON objected that contains the request body used to either create or update the Azure resource in question.

Once everything is set we can execute the required terraform commands.

terraform init

terraform plan

terraform apply

So probably, there isn't anything we can't terraform!

GitHub Repo: https://github.com/AnvaySingh/Azure-Blob