User Assigned Identity & Storage Account in Azure with Terraform

I had come across a situation where I got a mysql running in a Azure Vm & I have to upload database backup files to storage. So, for that purpose I have done this.

The goal is to create storage account container and access from VM using User Assigned Identity.

If User Assigned Identity is attached to VM, accessing storage account won't be much hard.

Most of the terraform code related to infra already shown in previous blog.

Let's start.

Storage Account

resource "azurerm_storage_account" "sa" {
  name                = "anilsdemo1"
  resource_group_name = azurerm_resource_group.rg.name

  location                 = azurerm_resource_group.rg.location
  account_tier             = "Standard"
  access_tier = "Hot"
  account_replication_type = "ZRS"

  network_rules {
    default_action             = "Deny"
    ip_rules                   = ["GIVE_YOUR_IP"]
    virtual_network_subnet_ids = [azurerm_subnet.subnet.id]
  }

  tags = {
    environment = "Test"
  }
}

replace "GIVE_YOUR_IP" with your public IP When I was creating container with terraform, it gave errors like

Error: containers.Client#GetProperties: Failure responding to request: StatusCode=403 -- Original Error: autorest/azure: Service returned an error. Status=403 Code="AuthorizationFailure" Message="This request is not authorized to perform this operation.\nRequestId:b1cbacae-901e-00f1-5233-d0f95c000000\nTime:2022-09-24T16:33:36.0925892Z"

So, I have tried giving my IP.

Create container in storage account

resource "azurerm_storage_container" "sa_container1" {
  name                  = "democontainer"
  storage_account_name  = azurerm_storage_account.sa.name
  container_access_type = "private"
}

Create User Assigned Identity

resource "azurerm_user_assigned_identity" "id1" {
    resource_group_name = azurerm_resource_group.rg.name
    location = azurerm_resource_group.rg.location
    name = "anilsuser1"
}

Assign a role for user id with storage account

resource "azurerm_role_assignment" "role1" {
    scope = azurerm_storage_account.sa.id
    principal_id = azurerm_user_assigned_identity.id1.principal_id
    role_definition_name = "Contributor"
}

You can give other roles in role_definition_name, check documentation for suitable one based on your use case.

Run terraform commands

$ terraform init

$ terraform plan
-> Plan: 9 to add, 0 to change, 0 to destroy.

$ terraform apply
-> Apply complete! Resources: 9 added, 0 changed, 0 destroyed.

Check Az login

Now, connect to VM using public key generated and VM Public

ssh -i ./tls/private.pem anil@VM_IP

Install Azure CLI with below command

$ curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

Copy values of user-id, storage_account_name, container_name from the terraform Outputs. They are required to login using az cli.

$ az login --identity -u /subscriptions/<subscription_id>/resourceGroups/tf-anils-demo/providers/Microsoft.ManagedIdentity/userAssignedIdentities/anilsuser1

$ az storage blob list --account-name anilsdemo1 -c democontainer --output table

$ echo $HOSTNAME > test.txt

$ az storage blob upload \
    --account-name anilsdemo1 \
    --container-name democontainer \
    --file test.txt

$ az storage blob list --account-name anilsdemo1 -c democontainer --output table
-> Name      Blob Type    Blob Tier    Length    Content Type    Last Modified              Snapshot
--------  -----------  -----------  --------  --------------  -------------------------  ----------
test.txt  BlockBlob    Hot          13        text/plain      2022-09-24T17:02:18+00:00


$ rm -rf test.txt

$ az storage blob download \
    --account-name anilsdemo1 \
    --container-name democontainer \
    --name test.txt \
    --file ./dowmload.txt


$ ls
dowmload.txt

Destroy resources

$ terraform destroy --auto-approve
-> Destroy complete! Resources: 16 destroyed.

Terraform Code available at Github

Check my articles at this blog.