Azure VM provisioning

How to set up an Azure VM - Windows and Linux - using Terraform or AZ CLI

Azure VM provisioning

I tend to use PaaS offerings more than VMs but when I do need VMs they always seem more complicated as time goes by.


We can provision a VM using az cli.

create a resource group

az group create --name my-vm-group --location uksouth

create the vm

az vm create \
    --resource-group my-vm-group \
    --name my-vm \
    --image MicrosoftWindowsDesktop:Windows-10:rs5-pro:latest \
    --assign-identity \
    --admin-username vmadmin \
    --admin-password some-convoluted-password

add the extension

az vm extension set \
    --publisher Microsoft.Azure.ActiveDirectory \
    --name AADLoginForWindows \
    --resource-group my-vm-group \
    --vm-name my-vm

add virtual machine role to user

(this can also be done manually in the azure portal through the IAM options of the vm)

username=$(az account show --query --output tsv)
vm=$(az vm show --resource-group my-vm-group --name my-vm --query id -o tsv)

az role assignment create \
    --role "Virtual Machine Administrator Login" \
    --assignee $username \
    --scope $vm

ensure the vm has a managed identity

ensure the domain user allowed to login has a Virtual Machine RBAC role

when using Apple MacOS as the host, you may encounter an error about not being able to use network level authentication. You need to log into the vm as the local admin account and disable network level authentication. Windows Explorer -> My PC -> Properties -> Remote Settings -> switch off network level authentciation

update: you can do this through the portal by using the RunCommand section.

Azure Linux VM AAD Authentication

Assuming you already have an Azure VM running we can use some az cli commands to add AAD authentication:


1. add extension to vm

az vm extension set \
    --publisher Microsoft.Azure.ActiveDirectory.LinuxSSH \
    --name AADLoginForLinux \
    --resource-group myResourceGroup \
    --vm-name myVM

2. provide role to domain user

username=$(az account show --query --output tsv)
vm=$(az vm show --resource-group kam-playground --name vm-playground --query id -o tsv)

az role assignment create \
    --role "Virtual Machine Administrator Login" \
    --assignee $username \
    --scope $vm

3. get vm ip

vmip=$(az vm show --resource-group kam-playground --name vm-playground -d --query publicIps -o tsv)

ssh -l vmip

The process works like this:

note: the 4a section in the diagram is flowing the wrong way but I couldnt be bothered to change the diagram. The VM polls the AAD endpoint for a 200 OK


I have three github repositories that illustrate how you can use terraform to provision an Azure VM for both Windows and Linux:

Lockdown groups

We can add users to local groups to lower the privileges. In this example we add an AAD user to the Power Users group.

net localgroup "Power Users" AzureAD\ /add

You can check who is in the group by running:

net localgroup "Power Users"

Other useful commands


get list of storage image reference publisher

$locName = "uksouth"
Get-AzVMImagePublisher -Location $locName | Select PublisherName

get list of offers

Get-AzVMImageOffer -Location $locName -PublisherName $pubName | Select Offer

get list of SKUs

Get-AzVMImageSku -Location $locName -PublisherName $pubName -Offer $offerName | Select Skus

get list of vm extensions

az vm extension image list --location uksouth -o table


What is the login user name format to login?


The sign-in method you’re trying to use isn’t allowed. Try a different sign-in method or contact your system administrator.

This may signify that your account is associated with MFA. Virtual machines dont like this. :(

Other reasons you may not be able to login

You have not added the user to IAM as a virtual machine user or administrative user.

You have not disabled network level authentication