5 ways Azure Copilot enhances your Azure Administration

Like many people, I’ve been using Azure Copilot to help with Azure Administration tasks and operations, and have seen how it can really help to enhance various aspects, taking the complexity out of tasks and operations, and providing guidance that I feel will benefit everyone using Azure – from seasoned experts to those new to Azure.

Copilot for Azure became Generally Available on the 8th April 2025 – you can read more about that here: https://techcommunity.microsoft.com/blog/azureinfrastructureblog/microsoft-copilot-in-azure-is-now-generally-available/4402033

In this post I’m going to highlight a few ways Azure Copilot can help, based on my own experience thus far! Please note – these are based on my own experience and usage, and are by no means exhaustive – these are designed as short examples to highlight the capabilities of Azure Copilot!


Deployment Help and Guidance

One key areas that Copilot can help with, is that of deployment – helping to guide us through the deployment process for a resource. For example – here is a prompt requesting help deploying the Azure Bastion Service. In this example, I simply asked “help me deploy Azure Bastion”, and the following guidance was then presented:

Options were also provided to show that PowerShell, Terraform and ARM Templates could also be used to deploy Azure Bastion too:

During my own testing, I also asked more specifically about deployment to a specific Virtual Network – and in this case, a more specific reply, tailored to my environment was provided:

As you can see, this guidance is tailored to the specific environmental aspects (in this case, a Virtual Network) that I requested – showing how Azure Copilot can integrate with our existing resources, and provided tailored guidance, specific to our environmental needs.


Infrastructure as Code

Infrastructure as Code is also an area where Azure Copilot can help – specifically around deployment of Azure Resources is where most of my testing has been. It’ll come as no surprise that most of my testing has been using Terraform, but Azure Copilot also excels at both Bicep and ARM too. Let’s test this out!

I started with a prompt to ask for help creating some Terraform:

Here’s the code provided – which is very useful for those needing to craft Terraform code quickly, and use this in their own deployments:

provider "azurerm" {
  features {}
}

variable "prefix" {
  default = "tfvmex"
}

resource "azurerm_resource_group" "example" {
  name     = "${var.prefix}-resources"
  location = "West Europe"
}

resource "azurerm_virtual_network" "example" {
  name                = "${var.prefix}-vnet"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
}

resource "azurerm_subnet" "bastion" {
  name                 = "AzureBastionSubnet"
  resource_group_name  = azurerm_resource_group.example.name
  virtual_network_name = azurerm_virtual_network.example.name
  address_prefixes     = ["10.0.1.0/27"]
}

resource "azurerm_public_ip" "example" {
  name                = "${var.prefix}-publicip"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name
  allocation_method   = "Static"
  sku                 = "Standard"
}

resource "azurerm_bastion_host" "example" {
  name                = "${var.prefix}-bastion"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name

  ip_configuration {
    name                 = "configuration"
    subnet_id            = azurerm_subnet.bastion.id
    public_ip_address_id = azurerm_public_ip.example.id
  }
}

resource "azurerm_network_interface" "example" {
  name                = "${var.prefix}-nic"
  location            = azurerm_resource_group.example.location
  resource_group_name = azurerm_resource_group.example.name

  ip_configuration {
    name                          = "internal"
    subnet_id                     = azurerm_subnet.bastion.id
    private_ip_address_allocation = "Dynamic"
  }
}

resource "azurerm_virtual_machine" "example" {
  name                  = "${var.prefix}-vm"
  location              = azurerm_resource_group.example.location
  resource_group_name   = azurerm_resource_group.example.name
  network_interface_ids = [azurerm_network_interface.example.id]
  vm_size               = "Standard_DS1_v2"

  storage_image_reference {
    publisher = "Canonical"
    offer     = "0001-com-ubuntu-server-jammy"
    sku       = "22_04-lts"
    version   = "latest"
  }

  storage_os_disk {
    name              = "${var.prefix}-osdisk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    managed_disk_type = "Standard_LRS"
  }

  os_profile {
    computer_name  = "hostname"
    admin_username = "testadmin"
    admin_password = "Password1234!"
  }

  os_profile_linux_config {
    disable_password_authentication = false
  }

  tags = {
    environment = "staging"
  }
}

Let’s now test this out with Bicep! Once again Copilot provides us with a suitable output – which we can then adjust as required for our own deployment process:

// The code was generated by AI which may result in unintended or inaccurate code. A human must validate that it accomplishes the desired goal before deploying the template.

@description('Name of the new resource group')
param resourceGroupName string

@description('Name of the virtual machine')
param vmName string

@description('Size of the virtual machine')
param vmSize string = 'Standard_DS1_v2'

@description('Admin username for the virtual machine')
param adminUsername string

@description('Admin password for the virtual machine')
@secure()
param adminPassword string

@description('Azure region for the resources')
param location string = resourceGroup().location

@description('Name of the virtual network')
param vnetName string = 'vnet01'

@description('IP prefix for available addresses in vnet address space')
param vnetIpPrefix string = '10.1.0.0/16'

@description('Specify whether to provision new vnet or deploy to existing vnet')
@allowed([
  'new'
  'existing'
])
param vnetNewOrExisting string = 'new'

@description('Bastion subnet IP prefix MUST be within vnet IP prefix address space')
param bastionSubnetIpPrefix string = '10.1.1.0/26'

@description('Name of Azure Bastion resource')
param bastionHostName string

var publicIpAddressName = '${bastionHostName}-pip'
var bastionSubnetName = 'AzureBastionSubnet'

// Create the resource group
resource rg 'Microsoft.Resources/resourceGroups@2021-04-01' existing = {
  name: resourceGroupName
}

// Create the public IP for Bastion
resource publicIp 'Microsoft.Network/publicIPAddresses@2022-01-01' = {
  name: publicIpAddressName
  location: location
  sku: {
    name: 'Standard'
  }
  properties: {
    publicIPAllocationMethod: 'Static'
  }
}

// Create a new virtual network and subnet for Bastion
resource newVirtualNetwork 'Microsoft.Network/virtualNetworks@2022-01-01' = if (vnetNewOrExisting == 'new') {
  name: vnetName
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        vnetIpPrefix
      ]
    }
    subnets: [
      {
        name: bastionSubnetName
        properties: {
          addressPrefix: bastionSubnetIpPrefix
        }
      }
    ]
  }
}

// Create Azure Bastion
resource bastionHost 'Microsoft.Network/bastionHosts@2022-01-01' = {
  name: bastionHostName
  location: location
  properties: {
    ipConfigurations: [
      {
        name: 'IpConf'
        properties: {
          subnet: {
            id: newVirtualNetwork.id + '/subnets/' + bastionSubnetName
          }
          publicIPAddress: {
            id: publicIp.id
          }
        }
      }
    ]
  }
}

// Create the virtual machine
resource vm 'Microsoft.Compute/virtualMachines@2022-03-01' = {
  name: vmName
  location: location
  properties: {
    hardwareProfile: {
      vmSize: vmSize
    }
    osProfile: {
      computerName: vmName
      adminUsername: adminUsername
      adminPassword: adminPassword
    }
    storageProfile: {
      imageReference: {
        publisher: 'MicrosoftWindowsServer'
        offer: 'WindowsServer'
        sku: '2019-Datacenter'
        version: 'latest'
      }
      osDisk: {
        createOption: 'FromImage'
      }
    }
    networkProfile: {
      networkInterfaces: [
        {
          id: newVirtualNetwork.id + '/subnets/' + bastionSubnetName
        }
      ]
    }
  }
}

Purely for the purposes of proving a point – let’s now try an ARM Template! In this case, a link to a template, complete with documentation via Microsoft Learn is provided:

So, as you can see, Azure Copilot is very capable when it comes to IAC too! For anyone working with IAC, this is hugely beneficial – having access to this within the Azure Portal, and readily available to use as required. What’s key here to Azure Copilot’s benefits too – is that context is important, and questions can be asked relating to our own Azure environment, and the Resources that we have access to.

You can read more about generating Terraform and Bicep using Azure Copilot here: https://learn.microsoft.com/en-us/azure/copilot/generate-terraform-bicep


Security

Azure Copilot can also help with security administration and guidance, and my testing has been with Azure Resources. It is important to remember that you can also utilise Microsoft Security Copilot too – read more about that here: https://learn.microsoft.com/en-us/copilot/microsoft-365/which-copilot-for-your-organization#microsoft-security-copilot

When considering Security within Azure Copilot, I tested and tried a few general aspects, as well as some specific elements for certain resources – you can see the results of these below, which give a good general overview of how Azure Copilot can help. Firstly, testing out Azure Policy – and understanding which baselines I could apply:

Whilst this provides more generic responses and guidance than a specific code example like those shared above, it demonstrates how Azure Copilot can assist in understanding the baseline policy recommendations – and provides links to further guidance and reading.

Next up, testing out securing a Key Vault:

So let’s take this a step further – and specifically ask for help enabling Soft Delete on one of my Key Vaults:

As you can see – this has provided specific guidance, for the Key Vault I specified. (Note that the Vault name has been hidden for security reasons). However, you can see that by asking this prompt, I’ve been given specific guidance, and a CLI command to use to enable the requested element. Whilst this is a specific example, it highlights the help Azure Copilot can give you for specific resources.


FinOps

As you will know, Azure has extensive cost management and control features, but sometimes, having a helping hand to guide you through understanding costs or where spend is occurring can really help. Within Azure Copilot, we have the opportunity to ask a range of questions related to Azure costs. My ability to demo this is slightly limited, as I am using an Azure Sponsorship Subscription, which is billed in a slightly different way. However, there are a range of great examples on Microsoft Learn:

In particular, the sample prompts here can really help you get started – and specifically highlight how different resources can be analysed for cost:

https://learn.microsoft.com/en-us/azure/copilot/analyze-cost-management?WT.mc_id=AZ-MVP-5004974#sample-prompts
https://learn.microsoft.com/en-us/azure/copilot/analyze-cost-management#sample-prompts

Testing this out in my own environment highlighted a good example – an unattached disk that could be removed to save costs:

Whilst the deep dive and data analysis options are key to cost management in Azure, via those available in Azure Cost Management, it’s still clear that Azure Copilot can provide a significant help for cost control and understanding, providing context around cost decisions and options.


Platform Operations and Enhancement

This section could be a whole blog post – there are numerous ways that Copilot for Azure assists here. One key aspect is providing information about specific resources and considerations, utilising information from elements like Azure Advisor, or for example, using prompts like “should I deploy an Azure Firewall or Azure App Gateway?”, which leads to the interaction shown below:

By providing this guided experience, Azure Copilot helps administrators to make decisions about their environment and services – and importantly, to then act upon this recommendation in a guided way. Here’s an example for Azure Firewall:

In certain cases, the whole experience can be guided – here’s me asking “Help me create a cost-efficient virtual machine” (one of the example prompts given in Microsoft Learn – https://learn.microsoft.com/en-us/azure/copilot/deploy-vms-effectively#create-cost-efficient-vms):

We are then guided further through this process:

Once we have completed these questions – we are then taken to the create VM wizard, with the B4ms size already selected. Although VM creation is a simple example of an administrative action – it highlights the help Azure Copilot can provide here.

I hope this post has been helpful – thanks for reading! 


Resources / Wider Reading
Skip to content