# Unlocking more Terraform Actions on Azure with AzAPI

When [Terraform Actions](https://developer.hashicorp.com/terraform/tutorials/configuration-language/actions) were unveiled at HashiConf 2025, they provided the foundation for a ton of potential around Day-2 ops. Unfortunately, all that potential seems to have created a challenge for figuring out exactly *what* actions to build. Six months later and we have... a total of five actions for AzureRM. What if I told you AzAPI has quietly unlocked many more?

*Let's take a dive into the vault (no, not that one!)*

![](https://cdn.hashnode.com/uploads/covers/69da8f7ac8e5007ddbd46077/19762ca0-db2e-4455-bf81-61655207c63f.gif align="center")

### Enter New Action: `action.azapi_resource_action`

As of December 2025, [2.80](https://github.com/Azure/terraform-provider-azapi/releases/tag/v2.8.0) version of the azapi provider added [`action.azapi_resource_action`](https://registry.terraform.io/providers/Azure/azapi/latest/docs/actions/resource_action) 🎉 On the surface it appears to just be a wrapper around a POST request - but the magic itself is in what you do with it. Using this action gives us the capability to run many different standard Azure stateless operations that *don't* fit into the standard lifecycle but exist today and can still benefit from existing as a native Terraform Action!

We can look at this action as the "gateway action", which is how it'll be referred to in the remainder of the post. Like most things in `azapi`, this action serves as a pioneer to the rest of the use-cases that `azurerm` will likely catch up with in the future.

*Until then...*

![](https://cdn.hashnode.com/uploads/covers/69da8f7ac8e5007ddbd46077/9232592d-1399-4aed-85f3-7a936853f0bb.png align="center")

*Come to the AzAPI side.... we have Actions.*

> **Example 1:**
> 
> Say that we have a storage account that needs its key rotated for... [reasons](https://orca.security/resources/blog/azure-shared-key-authorization-exploitation/). Well, add the below action to your `.tf` file and, voilá! You now have an almost magic way you can rotate the key whenever you want right from `terraform`

```go
# terraform apply -invoke-action azapi_resource_action.rotate_storage_account_key
action "azapi_resource_action" "rotate_storage_account_key" {
  config {
    type        = "Microsoft.Storage/storageAccounts@2023-05-01"
    resource_id = azurerm_storage_account.this.id
    action      = "regenerateKey"
    method      = "POST"
    body = {
      keyName = "key1"
    }
  }
}
```

> **Example 2:**
> 
> Our Kubernetes clusters in the dev environment are getting [EXPENSIVE](https://www.convox.com/blog/cost-of-running-k8s). Well, add the below action to your `.tf` file and, voilá! You now have an almost magic way you can stop/start your AKS whenever you want right from `terraform`

```go
# terraform apply -invoke-action azapi_resource_action.aks_stop
action "azapi_resource_action" "aks_stop" {
  config {
    type        = "Microsoft.ContainerService/managedClusters@2024-02-01"
    resource_id = azurerm_kubernetes_cluster.this.id
    action      = "stop"
    method      = "POST"
  }
}

# terraform apply -invoke-action azapi_resource_action.aks_start
action "azapi_resource_action" "aks_start" {
  config {
    type        = "Microsoft.ContainerService/managedClusters@2024-02-01"
    resource_id = azurerm_kubernetes_cluster.this.id
    action      = "start"
    method      = "POST"
  }
}
```

### Five Reasons to use a Terraform Action

1.  Does not require separate tooling - purely `terraform`
    
2.  AuthN/AuthZ handled by your existing Terraform provider configuration
    
3.  Centralized, auditable record of which actions were invoked across control planes
    
4.  Your operation is stateless - no response needed and thus can run independently of the standard CRUD lifecycle
    
5.  `action` blocks are semantically distinct from `resource` blocks: future maintainers will thank you
    

### More Things the "Gateway Action" Unlocks

*   Regenerate all the keys! Storage accounts, Redis Clusters, Event Hubs, and many more can use something similar/same as the `regenerateKey` example above.
    
*   Ensure your app is running by using App Services `slotswap` to manually swap a slot (because staging was broken and is now production! Oh and it's also 2am!) and `syncfunctiontriggers`, ensuring Function Apps are updated if they don't register properly after config changes
    
*   `stop` & `start` or `deallocate` & `allocate` resources when they're not being used (e.g. non-prod environments). This one can apply to 🥁: AKS clusters, Azure Firewall, SQL Managed Instances, SQL Data Warehouses, Kusto (ADX) Clusters, the list goes on...
    

### What it Doesn't Do

So, is this all magic? Unfortunately it's only partially magical, so the main thing that's missing with `action.azapi_resource_action` are **calling data plane endpoints** (and rightly so).

Like many `azurerm` issues that have come before, we don't currently have the ability to manage the actual data inside of services. This could be something like purging a certificate off of Azure Key Vault, or even surprisingly through this post learning that some services (e.g. Azure Databricks) cannot have their clusters stopped / started via the management plane - these are data plane only endpoints. Since the gateway action only works on the management endpoints it's unable to perform these data plane actions.

### The Takeaway

The AzAPI gateway action unlocks a lot of potential that AzureRM hasn't caught up to yet, and it's available right now! I'm working on something that takes this pattern further into AI skills territory and am excited to share this with you all.

Please feel free to follow or shoot me a message to stay updated on how we can unlock further ease of Day-2 Ops using Terraform Actions.

Until next time, IaC practitioner 👋🏻

![](https://cdn.hashnode.com/uploads/covers/69da8f7ac8e5007ddbd46077/b249cbdf-d8a6-4638-9b48-97fecc6ed531.gif align="center")
