As your team begins to provision and configure more Windows Azure virtual machines (VMs), at some point, you'll get tired of reinventing the wheel. You need automation! In this article, come with me as I walk you through step-by-step to begin using Azure custom script extensions for Windows to speed up deployment and configuration.

If your team is in a Windows environment, one of the best tools to automate server configuration is PowerShell. By using the Azure PowerShell module your team can leverage the power of PowerShell to not only automate on-prem tasks but also run commands on Azure VMs in bulk rather than one at a time.

One feature Microsoft has provided us is called the Azure custom script extension. The custom script extension is an Azure virtual machine extension that the VM agent runs to execute arbitrary PowerShell code against your VMs by using the Azure API rather than consoling into the VM or using PowerShell remoting.

Running commands this way provides several benefits. Running commands using the Azure custom extension in Windows:

  • provides increased security by not needing to open network ports for PowerShell remoting
  • allows for easy executing PowerShell code at VM startup
  • automatically transferring resources from Azure storage to your VM as part of the provisioning process
  • an easy way of running PowerShell scripts stored in various Azure storage accounts

Enabling an Azure custom script extension for Windows can be done in a few ways. In this article, we'll be focusing on enabling the custom script extension via PowerShell, but you may also enable the extension via an Azure Resource Manager(ARM) template.

As a simple example, let's say you'd like to ensure PowerShell remoting is enabled on an Azure VM in your subscription. To do this, you'd need to run the following command locally on each VM:

Enable-PSRemoting -Force

Let's build a custom script extension to do this.

Building an Azure Custom Script Extension for Windows

First, create a PowerShell script called Enable-PSRemoting.ps1 on your local computer with the command above inside. This script needs to run on an Azure VM. To do this, we'll build another small PowerShell script called New-CustomScriptExtension.ps1 to get it uploaded into Azure and a custom script extension created to execute it. Before we get too far, you'll need a couple items:

  • The Azure resource group and storage account name that will store the script
  • The Azure storage container name
  • The VM name
  • The Azure resource group name that the VM is in

This script can be broken down two sections; getting the small PowerShell script uploaded and Azure and creating the custom script extension. Everything else is required to glue these two processes together.

Uploading a PowerShell Script to Azure

First, we'll upload the Enable-PSRemoting.ps1 script to the Azure storage account ($StorageAccountName) inside of the container ($ContainerName) in the resource group ($ResourceGroupName).

$saParams = @{
    'ResourceGroupName' = $ResourceGroupName
    'Name' = $StorageAccountName
}
$storageContainer = Get-AzureRmStorageAccount @saParams |Get-AzureStorageContainer -Container $ContainerName
$bcParams = @{
    'File' = 'C:\Enable-PSRemoting.ps1'
    'BlobType' = 'Block'
    'Blob' = ' Enable-PSRemoting.ps1'
}
$storageContainer | Set-AzureStorageBlobContent @bcParams
Copying Enable-PSRemoting.ps1 to Azure

Running the Custom Script Extension

When you run New-CustomScriptExtension.ps1, this script will upload the Enable-PSRemoting.ps1 script to the Azure storage account specified.

Now that the script is stored in Azure, you can execute it via the custom script extension for the VM:

  • Name: $VMName
  • Resource Group: $rgName
  • Storage Account: $saName
  • Storage Container: $scName

Open up a text editor for New-CustomScriptExtension.ps1 and paste in the below example. When you run this, it will execute the Azure custom script extension for Windows which will execute the Enable-PSRemoting.ps1 PowerShell script you uploaded earlier.

# Get the VM we need to configure
$vm = Get-AzureRmVM -ResourceGroupName $rgName -Name $VMName
# Get storage account key
$key = (Get-AzureRmStorageAccountKey -Name $saName -ResourceGroupName$rgname).Key1
## Enable the custom script extension and run the script
$scriptParams = @{
    'ResourceGroupName' = $rgName
    'VMName' = $VMName
    'Name' = 'Enable-PSRemoting.ps1'
    'Location' = $vm.Location
    'StorageAccountName' = $saName
    'StorageAccountKey' = $key
    'FileName' = 'Enable-PSRemoting.ps1'
    'ContainerName' = $scName
    'Run' = 'Enable-PSRemoting.ps1'
}
Set-AzureRmVMCustomScriptExtension @scriptParams
New-CustomScriptExtension.ps1

Summary

Once this script completes, you can verify that Enable-PSRemoting.ps1 has executed on the VM and PowerShell remoting has been successfully enabled. You should now be able to use Invoke-Command against your Azure VM.

By leveraging the Azure custom script extension in Windows, you now have the ability to remotely run any kind of PowerShell scripts on your Azure VMs.

Join the Jar Tippers on Patreon

It takes a lot of time to write detailed blog posts like this one. In a single-income family, this blog is one way I depend on to keep the lights on. I'd be eternally grateful if you could become a Patreon patron today!

Become a Patron!