Using PowerShell Desired State Configuration (DSC) within your Azure environment? I recommend looking at using Azure Automation to assist you with this!
The Azure Automation account which will hold DSC configurations and compiled configs along with imported modules acts as the DSC “pull server”. Along with this, has a great User Interface to check if the node is compliant or if there is any issues with the DSC configuration being applied.
Lets look at the prerequisites when looking to deploy the above
Operating System Requirements
Following Windows versions supported
- Windows Server 2008 R2 SP1 -> Windows Server 2019
- Windows 7, 8.1 & 10
Although with PowerShell being Windows native, all versions of Linux supported by Azure should work correctly with the DSC Linux extension except for :-
- Debian – All Versions
- ubuntu – 18.04
Operating systems running in a private network? These ports and URLs will be needed to be configured to allow access (taken from docs.microsoft)
- Port: Only TCP 443 is required for outbound internet access.
- Global URL: *.azure-automation.net
- Global URL of US Gov Virginia: *.azure-automation.us
- Agent service: https://workspaceId.agentsvc.azure-automation.net
Lets Deploy!
For this tutorial, I will want to install and configure a simple IIS web site on a Windows Server 2012 R2 Virtual Machine using PowerShell DSC
Create Automation Account: tamopsautomation and Resource Group: tamopsautomationtest
$resourceGroupLocation = "eastus"
$resourceGroupName = "tamopsautomationtest"
$automationAccountName = "tamopsautomation"
az group create -l $resourceGroupLocation -n $resourceGroupName
New-AzureRmAutomationAccount -Name $automationAccountName -Location $resourceGroupLocation -ResourceGroupName $resourceGroupName
When an Automation Account has been deployed, it will have a set of modules that can be referenced within your DSC configuration, lets have a quick review of these

An additional module will be required: xWebAdministration
Add this from the gallery, clicking import

I have created two files:
- WebConfiguration.ps1 – Requirements for DSC config to install/configure
- WebCompile.ps1 – Compile the configuration file and upload to Automation Account
WebConfiguration.ps1
configuration WebConfiguration
{
Import-DscResource -ModuleName 'xWebAdministration'
Import-DscResource -ModuleName 'PSDesiredStateConfiguration'
WindowsFeature Web-Server
{
Ensure = 'Present'
Name = 'Web-Server'
}
WindowsFeature Web-Mgmt-Tools
{
Ensure = 'Present'
Name = 'Web-Mgmt-Tools'
}
xWebsite DefaultSite
{
Ensure = 'Present'
Name = 'Default Web Site'
State = 'Stopped'
DependsOn = '[WindowsFeature]Web-Server'
}
xWebsite TamOpsTestSite
{
Ensure = 'Present'
Name = 'TamOps Test Site'
State = 'Started'
PhysicalPath = 'C:\inetpub\wwwroot'
DependsOn = '[WindowsFeature]Web-Server','[xWebsite]DefaultSite'
}
}
WebCompile.ps1
$ConfigData = @{
AllNodes = @(
@{
NodeName= "*"
PsDscAllowPlainTextPassword = $true
}
)
}
$resourceGroupLocation = "eastus"
$resourceGroupName = "tamopsautomationtest"
$automationAccountName = "tamopsautomation"
$DscSourcePath = 'C:\Users\thomast\TamsOps\Azure Automation\WebConfiguration.ps1'
Import-AzureRmAutomationDscConfiguration -ResourceGroupName $resourceGroupName -AutomationAccountName $automationAccountName -SourcePath $DscSourcePath -Published -Force
Start-AzureRmAutomationDscCompilationJob -ResourceGroupName $resourceGroupName -AutomationAccountName $automationAccountName -ConfigurationName 'WebConfiguration' -ConfigurationData $ConfigData -Verbose
Running WebCompile.ps1 will output:
ResourceGroupName : tamopsautomationtest
AutomationAccountName : tamopsautomation
Location : eastus
State : Published
Name : WebConfiguration
Tags : {}
CreationTime : 27/03/2019 08:44:55 +00:00
LastModifiedTime : 27/03/2019 08:44:55 +00:00
Description :
Parameters : {}
LogVerbose : False
VERBOSE: Performing the operation "Start" on target "WebConfiguration".
ResourceGroupName : tamopsautomationtest
AutomationAccountName : tamopsautomation
Id : f54e1e83-0824-4b38-a0f1-5bff757765f4
CreationTime : 27/03/2019 08:44:57 +00:00
Status : Completed
StatusDetails : None
StartTime : 27/03/2019 08:45:39 +00:00
EndTime : 27/03/2019 08:45:46 +00:00
Exception :
LastModifiedTime : 27/03/2019 08:45:46 +00:00
LastStatusModifiedTime : 27/03/2019 08:45:46 +00:00
JobParameters : {ConfigurationData}
ConfigurationName : WebConfiguration
Reviewing the Automation Account: tamopsautomation you can now see there is a DSC configuration available WebConfiguration

Clicking on this configuration we can see there is a successful completion job, this will now be available to deploy onto a Virtual Machine

Deploy DSC Configuration to VM
This can also be deployed via AzureRM when deploying your Virtual Machine
Inside Automation Account: tamopsautomation -> State Configuration (DSC) -> Click Add
Select Virtual Machine you want DSC Config to deploy to and select Connect and configure as per below

Once successfully connected, you can wait the refresh frequency above or log onto VM and run
Update-DscConfiguration -wait -Verbose
Reviewing the output, we can see that it has
- Installed Windows Feature: Web-Server
- Installed Windows Feature: Web-Mgmt-Tools
- Stopped WebSite: Default Web Site
- Created and started Website: TamOps Test Site
PS C:\Users\thomast> Update-DscConfiguration -wait -Verbose
VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = PerformRequiredConfigurationChecks,'className' = MSFT_DSCLocalConfigurationManage
r,'namespaceName' = root/Microsoft/Windows/DesiredStateConfiguration'.
VERBOSE: An LCM method call arrived from computer tamopsvm with user sid S-1-5-21-1434058460-3316421413-3330547948-500.
VERBOSE: [tamopsvm]: [] Executing Get-Action with configuration (null)'s checksum: .
VERBOSE: [tamopsvm]: [] Executing Get-Action with configuration 's checksum returned result status: GetConfiguration.
VERBOSE: [tamopsvm]: [] Checksum is different. LCM will execute GetConfiguration to pull configuration .
VERBOSE: [tamopsvm]: [] Executing GetConfiguration succeeded. Configuration was pulled from server.
VERBOSE: [tamopsvm]: [] Applying the new configuration(s) pulled.
VERBOSE: [tamopsvm]: LCM: [ Start Resource ] [[WindowsFeature]Web-Server]
VERBOSE: [tamopsvm]: LCM: [ Start Test ] [[WindowsFeature]Web-Server]
VERBOSE: [tamopsvm]: [[WindowsFeature]Web-Server] The operation 'Get-WindowsFeature' started: Web-Server
VERBOSE: [tamopsvm]: [[WindowsFeature]Web-Server] The operation 'Get-WindowsFeature' succeeded: Web-Server
VERBOSE: [tamopsvm]: LCM: [ End Test ] [[WindowsFeature]Web-Server] in 0.6560 seconds.
VERBOSE: [tamopsvm]: LCM: [ Skip Set ] [[WindowsFeature]Web-Server]
VERBOSE: [tamopsvm]: LCM: [ End Resource ] [[WindowsFeature]Web-Server]
VERBOSE: [tamopsvm]: LCM: [ Start Resource ] [[WindowsFeature]Web-Mgmt-Tools]
VERBOSE: [tamopsvm]: LCM: [ Start Test ] [[WindowsFeature]Web-Mgmt-Tools]
VERBOSE: [tamopsvm]: [[WindowsFeature]Web-Mgmt-Tools] The operation 'Get-WindowsFeature' started: Web-Mgmt-Tools
VERBOSE: [tamopsvm]: [[WindowsFeature]Web-Mgmt-Tools] The operation 'Get-WindowsFeature' succeeded: Web-Mgmt-Tools
VERBOSE: [tamopsvm]: LCM: [ End Test ] [[WindowsFeature]Web-Mgmt-Tools] in 0.3130 seconds.
VERBOSE: [tamopsvm]: LCM: [ Skip Set ] [[WindowsFeature]Web-Mgmt-Tools]
VERBOSE: [tamopsvm]: LCM: [ End Resource ] [[WindowsFeature]Web-Mgmt-Tools]
VERBOSE: [tamopsvm]: LCM: [ Start Resource ] [[xWebsite]DefaultSite]
VERBOSE: [tamopsvm]: LCM: [ Start Test ] [[xWebsite]DefaultSite]
VERBOSE: [tamopsvm]: [[xWebsite]DefaultSite] The state of website "Default Web Site" does not match the desired state.
VERBOSE: [tamopsvm]: [[xWebsite]DefaultSite] The target resource is not in the desired state.
VERBOSE: [tamopsvm]: LCM: [ End Test ] [[xWebsite]DefaultSite] in 0.1870 seconds.
VERBOSE: [tamopsvm]: LCM: [ Start Set ] [[xWebsite]DefaultSite]
VERBOSE: [tamopsvm]: [[xWebsite]DefaultSite] State for website "Default Web Site" has been updated to "Stopped".
VERBOSE: [tamopsvm]: LCM: [ End Set ] [[xWebsite]DefaultSite] in 0.1250 seconds.
VERBOSE: [tamopsvm]: LCM: [ End Resource ] [[xWebsite]DefaultSite]
VERBOSE: [tamopsvm]: LCM: [ Start Resource ] [[xWebsite]TamOpsTestSite]
VERBOSE: [tamopsvm]: LCM: [ Start Test ] [[xWebsite]TamOpsTestSite]
VERBOSE: [tamopsvm]: [[xWebsite]TamOpsTestSite] The state of website "TamOps Test Site" does not match the desired state.
VERBOSE: [tamopsvm]: [[xWebsite]TamOpsTestSite] The target resource is not in the desired state.
VERBOSE: [tamopsvm]: LCM: [ End Test ] [[xWebsite]TamOpsTestSite] in 0.0310 seconds.
VERBOSE: [tamopsvm]: LCM: [ Start Set ] [[xWebsite]TamOpsTestSite]
VERBOSE: [tamopsvm]: [[xWebsite]TamOpsTestSite] State for website "TamOps Test Site" has been updated to "Started".
VERBOSE: [tamopsvm]: LCM: [ End Set ] [[xWebsite]TamOpsTestSite] in 0.1250 seconds.
VERBOSE: [tamopsvm]: LCM: [ End Resource ] [[xWebsite]TamOpsTestSite]
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 3.202 seconds
Checking the IIS Manager

We can now review the compliance status of this virtual machines DSC in the Portal

Success!
Hopefully this blog has given you an understanding into PowerShell DSC and Azure Automation DSC!