Change Azure VM Primary Network Interface | Azure Virtual Machines, VM Network Interfaces, VM Multiple NIC

In some cases you might require changing the marked primary network interface of an Azure Virtual Machine with multiple Network Interfaces.

I ran into this when trying to set a Public IP Address on a non-primary Network Interface.


This process is very straight forward, but can only be done in PowerShell.

To check and see which network interface you wish to set as primary, you can see the index details from a Get-AzureRmVM -Name VMNAME -ResourceGroupName VMRG



Role Based Access Control (RBAC) in Azure and Custom Policies | Azure RBAC, Azure Custom RBAC Policies, PowerShell, Azure ARM

Azure offers 2 management portals and 2 different deployment models – Azure Resource Manager (ARM) and Azure Service Manager (ASM). Both models offer similar Azure services such as Virtual Networks and Virtual Machines, but some features are only available in one versus the other.

Administrator access is the only option available in the ASM model. As a result of this limitation Microsoft has developed the second generation model for Azure called ARM which includes Role Based Access Control (RBAC). Using ARM, granular access is provided to specific groups of resources or single objects in Azure.

Role-Based Access Control (RBAC) in the Azure Portal and Azure Resource Management API allows administrators to manage access to the subscription at a fine-grained level. With this feature, administrators can grant access for Active Directory users, groups, or service principals by assigning some roles at a particular scope.

Below is a diagram of an RBAC methodology that I implemented for a customer. Management of resources and application lifecycles are managed at the Resource Group Level and where all RBAC policies are applied.


Azure provides 39 built-in RBAC roles. These roles provide specific action or no action to specific resource objects within the Azure Subscription. For the most part, these built-in roles will satisfy most management operation.

For an up to date list please visit:

You can also export the list using the following command in PowerShell while connected to the Azure Subscription:

Custom RBAC Roles

Custom RBAC Roles are used when the Built-In roles do not provide enough security or granularity to a specific administrative task or when trying to grant specific access to a resource.

Azure Custom RBAC roles are initially created by downloading a JSON file closest to what you wish the new custom role to do. This helps not having to specify all the actions or no-actions required for the new role.

For this post we will create a custom RBAC policy that will allow a user to join their virtual machine to an existing Virtual Network, but give them no access to modify/delete the Virtual Network. In an organization where you want developers, IT etc. to deploy workloads and to leverage existing VPN/ExpressRoute for on-premises connectivity but need to control who has access to modify, delete this type of policy becomes very handy.

The role that will be used to create the custom RBAC role will be the Virtual Machine Contributor built-in role as the role provides the virtual network read and subnet join actions.


The following actions are required to provide access to join a specific Virtual Network.

The following command will download the JSON file for the built-in role which will allow us to modify and use it to create our new custom role.

The downloaded JSON file will look like this.


In order for any action to be performed on an object, such as modify or delete, the role must also be provided the read action. The section action is to allow join on the virtual network subnets.

The new custom RBAC JSON file will look like this.


The Assignable Scopes field in the JSON Policy is the level at which the policy will be applied. This can be at a subscription, resource group and even resource levels.

In order the create the new role run the following command:

Once the custom RBAC policy has been created in Azure, permissions can be granted to AD groups or AD Users for that role.



Until next time.

Tim Day


Gotcha: Azure VM NIC DNS Settings when using Availability Sets | Azure DNS Settings, Availability Sets, Azure ARM Networking

When deploying Windows Virtual Machines in Azure and assigning them into the same Availability Set for Azure 99.9% SLA there is one thing to remember. In common practice when deploying Domain Controllers, you would set your DNS Settings to reflect the DC IP Addresses in the order of itself then the second, third etc…

DC01 – then
DC02 – then

When these servers are in an Availability Set, Azure will only allow for a consistent DNS list across all the servers in the Set. And it is not recommended to change this in Windows.

You can set the DNS Settings to whatever you want in the Network Interface DNS settings but all the servers will be provided the same IPs in the same order.



Notice the order of the “DnsServers” and the “AppliedDnsServers”


This is not a show stopper, but something to be aware of. I tried to set the AppliedDnsServers list to the desired listing via PowerShell but the settings did not stick.



If anyone knows of a way to get around this please post your comments below. Again not a huge problem but always a good to know before you spend time troubleshooting something you cant fix 🙂


Tim Day

Create User Defined Route (UDR) to Route Azure Traffic when using Forced Tunneling | User Defined Route, UDR, Azure, Forced Tunneling

Some customers require that all communication to/from Virtual Machines in Azure be sent over their VPN or ExpressRoute. But this causes issues when these Virtual Machines require access to an Azure resource such as KMS for Windows Activation or communicating with other Azure services such as SQL DB.

Personally I don’t see a real need to use forced tunneling when you can lock down communication to/from your virtual machines by using Network Security Groups (NSG) and route only what you need to on-premises by creating a UDR with only your on-premises local subnets. But its always business requirements that keep things interesting.

For these scenarios I have created a PowerShell Script that takes all the Azure Datacenter IP Addresses for the region (East US in this case) and create a UDR which will be assigned to the Virtual Network subnet.

All the Scripts and Templates used in this blog post can be found at

First download the Azure Datacenter IP XML List –

Next is to create a CSV file with 3 columns – routeName, addressPrefix and NextHopType

NOTE: Some Datacenters like East US have over 200 IP Addresses and you must open a ticket with Azure Support to have the default limit increased from 200 to 400 IP Addresses per UDR.

The CSV once completed will look like the below screen snip.


The nextHopType column specifies where do we want this traffic to go, if this wasn’t the internet and a next Gen Firewall we would specify the gateway and nextHopIP Address.

Next take the PowerShell Script below and copy it into a local .ps1 this script will take the values from the CSV and import into Azure.

Finally connect to AzureRM and run the ps1 script above and depending on how many IP Addresses are in your CSV this could take 1-4 minutes to complete.

As I mentioned before this is not a normal configuration and is usually required only when specific company’s require it. but I hope this post was helpful, and feel free to change the script for your own needs! the main reason for this post 🙂

Tim Day

Link ARM and ASM Virtual Networks to Azure ExpressRoute Circuit | Azure Networking, ExpressRoute, ASM and ARM, Linking Virtual Networks

Microsoft Azure provides a method of linking ASM Virtual Networks to ARM ExpressRoute circuits. But note that the circuit must be ARM you cannot link ARM Virtual Networks to ASM Circuits.

In this post I will cover enabling an ExpressRoute ARM Circuit to allow linking of ASM (Classic) Virtual Networks, as well as linking both an ASM Virtual Network in the same Subscription as the ExpressRoute Circuit and an ARM Virtual Network in another Subscription.

Prerequisites for this post assume that you have already created and have a working ExpressRoute Circuit and that your ARM and ASM Virtual Networks have been created and with the Gateway’s already provisioned (Gateway’s can take 30-60 minutes to deploy)

There is a setting for the ExpressRoute Circuit which is only viewable via PowerShell and is the AllowClassicOperations. By default this option is set to false which we need to set to true by running the following command – remember to select the subscription that the circuit is in if you have multiple subscriptions

The final command Set-AzureRmExpressRouteCircuit can take a few minutes to complete and might look like its hanging.


After confirming that the ExpressRoute Circuit is now allowing classic operations we can now link our Classic or ASM Virtual Network to our ARM Circuit.

First we need to create a dedicated circuit link, think of this as an authorization for other Virtual Networks to link to the ExpressRoute Circuit. Also note that this can only be done with the Premium Add-on ExpressRoute Gateway.

After a few minutes you should see the link connect in the ASM (Classic) Portal.



Link ARM Virtual Network in Another Subscription

Next is to create an Authorization on the ARM ExpressRouteCircuit, this will generate an authorization key that we will need to use in a below command to link the ARM Virtual Network in another subscription with the ExpressRoute Circuit.

Next command will apply the new authorization to the ExpressRoute Circuit

Once the configuration has applied you will see a final output, at the bottom of the output you will see the new authorization along with the authorization key.


Next we will link the ARM Gateway to the ExpressRoute Circuit using the authorization key. Remember to do this from your Virtual Network Subscription that you are trying to link. If you do this from the ExpressRoute Subscription the command will fail.

At this point your ARM Virtual Network in another subscription will be linked to your ExpressRouteCircuit. With a premium ExpressRoute Gateway you can even link Virtual Networks in other regions not just different subscriptions using the commands above.

See the screen snip blow – Linked Virtual Network from South East Asia in Subscription 3269 to an ExpressRoute Circuit in the East US Datacenter in the ffee9 subscription.


Until the next time, happy networking!

Tim Day

Working with Azure Automation, Desired State Configuration and Template Extensions | Azure Automation, Desired State Configuration, Template Extensions

In this post I will demo a Desired State Configuration (DSC) using Azure Automation to push the configuration to a Windows Azure VM.

This post we will configure the following:

  • Desired State Configuration
    • Set Time Zone
    • Download and Install Application
  • Configure Azure Automation Account
    • Provide Storage credentials using Credential Asset

Also I will show the PowerShell DSC extension in JSON for template deployment which will also add the Azure Automation account to the VM DSC Extension during deployment.

All the Scripts and Templates used in this blog post can be found at

Desired State Configuration

DSC uses resources and like with PowerShell resources are PowerShell modules. The module contains both the schema and the implementation code for the DSC resource.

Within a configuration file multiple modules can be imported and called to resources to perform multiple configuration actions. This could be to install an application, change registry, domain join as a few examples.

There is a large community of modules that have already been created to perform some sort of configuration action, and if not just like in PowerShell with DSC you can create your own modules. But well save custom modules for another post.

The Microsoft PowerShell Team provides an excellent repository with a very large collection of DSC and PowerShell modules and scripts –

And for this demo we will use the following modules:

PSDesiredStateConfiguration – This is the standard DSC Module provided by Microsoft
xTimeZone – This is a community module and will be used to set the VM time zone to Eastern Standard Time.

Next is to call some resources to perform both our package installation and setting the time zone. When working with new Modules I would check out the README information for the module in GitHub which will provide you the necessary information needed to work with the module.

With the PSDesiredStateConfiguration module we will be using a few resources – The File resource to download the package and the Package resource to perform the installation.

As you can see in the below code snip each resource that’s called as part of the DSC specifies some sort of property such as Arguments and DependsOn. These properties assist with the customization of the deployment of the resource as per your requirements.

You’ll also notice in the code snip above that the Credential parameter is calling on $PackageCredential. This is actually calling a Credential Asset from Azure Automation.

Below is the Full DSC Configuration Script that we will be using to import into Azure Automation.


Configure Azure Automation Account

Azure Automation provides an excellent way of pushing out configurations without requiring to build your own DSC push server infrastructure, and allows for you to save assets to call on at anytime via DSC or a Run Book. For this demo we will be using Azure Automation using Azure Resource Manager.


First we need to import our modules, this is done via the settings blade in the Azure portal once you open your Automation account and click Assets. Next click on Modules then Browse gallery from the top. Microsoft has made this very convenient to import modules directly from the Automation Account.

Next search for the xTimeZone module and click import from the xTimeZone details blade.


Next go back to your Assets window and click the Credentials Asset. Click Add a credential, this credential will be used to connect to the Azure Files account where my package is being stored.

When creating the name for the credential asset, remember this is the name that will be used in the DSC configuration when we call it via the $PackageCredential.


Now we have our assets configured in Azure Automation, next we import our DSC Configuration into Azure Automation which behind the senses packages the .ps1 into a MOF configuration which will be pushed to the Virtual Machine.

Back on the main Azure Automation blade, click DSC Configurations and Add a configuration from the top menu of the next blade.


On the Import Blade, click the browse on Configuration file and locate your DSC Configuration.ps1 file. You’ll notice the Name field auto populates with the configuration name you specified in your deployment. so for this demo the configuration name is MYLAB_DSC_DEMO


Once you have clicked on OK and imported the DSC configuration you will notice if you click on the configuration it will pull up another blade and under the Compilation jobs there is nothing.. yet. Next we need to tell Azure Automation to compile this configuration into a MOF that will be used by the Windows Virtual Machine.

This next step will require us to go into PowerShell to kick off the compile of the DSC configuration. This is because we need to pass some configuration parameters to Azure Automation for the compile. One of these parameters is the passwords in plain text. The word PLAIN TEXT is not usually taken well especially with your security department, but there is an upside.


When Azure Automation compiles the configuration and takes the password from the encrypted state in an automation password asset and passes it into the MOF file with this solution of using a plain text parameter the password will be stored in plain text. BUT there is actually no visibility into the actual MOF file sitting within an Azure Automation Server in the Azure Datacenter.

And Microsoft even confirms that the entire MOF is encrypted. So in my mind, if there is no real requirement to secure the password encrypted adding the plain text parameter to Azure Automation is a much more simplified but still secure approach.

But as a consultant we provide pros and cons to all solutions and scenarios and follow customer requirements.

Save the below code into a .ps1 and run it once connected to Azure PowerShell. Remember to change the code to reflect your Automation Account, Configuration Name and Resource Group.


Now go back to the DSC Configuration blade and you should now see the compilation job – different status will be Queued, Starting, Running, Completed and Suspended.




Deploying Virtual Machine with DSC Configuration

The final step is to deploy the virtual machine with the PowerShell DSC extension and to configure the extension to use the Azure Automation account and the newly imported configuration.

I’m not going to go into detail on the ARM template it self, as there is a ton of templates to choose and learn from via the Azure GitHub Repository –

But the Extension resource which can be added to just about any existing VM Template code is below. Notice that all the configuration is coming from variables – I find this much easier to work with templates and modifying only variables then modifying throughout the template.

You can find your registration URL and registration private keys by clicking the key icon from the top right side of the Automation Account Blade.


In the extension resource you only need to change the “registrationKeyPrivate”: to the one provided by your Azure Automation Account.

For the variables change the automationregistrationURL to your Automation Account URL as well as the automationNodeConfigurationName, for this demo it will be MYLAB_DSC_DEMO.localhost

Once we have the extension, variables and modifications added to the template we will go head and deploy the Virtual Machine.

And as you can see during the deployment we can see the Compute resource completed (VM Deployed) and the DSC Extension. Once the deployment is complete we can verify that the VM has been successfully added to the Azure Automation Nodes blade and can see that the configuration is in-progress.



Once complete we can login to the Virtual Machine and verify our configuration.

Time Zone Eastern Standard Time – Check!

Installed Application – Check!


I hope you have enjoyed this post and hope it helps show the power of Azure Automation and building DSC configurations for all your repeatable server deployments. And remember we did this with a VM in Azure but as long as the server requiring DSC has internet access the server can be anywhere, On-Premises even Azure Stack!.

Until the next time!

Tim Day

Working with Linked Templates in Azure | Linked Templates, Azure, JSON Templates

Azure ARM JSON Templates is something I have been working with quite a bit over the last few months for a customer. They have a requirement that all templates must allow for standardization for IaaS resources as well as provide rapid deployment if 1 or 10 Virtual Machines are required.

Using linked or nested templates allow for greater flexibility and when requiring to customize only the linked template(s) require customization.

All the Scripts and Templates used in this blog post can be found at

The master template (azuredeploy.json) captures the user input parameters like all templates but where things get fancy is in the resources section of the template where we don’t call virtual machines or extension reources but we call Microsoft.Resource/deployments and call the linked template within the properties.

Additionally, the parameters in the code snip above actually takes the variables from the master azuredeploy.json file and passes them to the linked template.

Then we create the linked template and specify the parameters

And when needing to use the variables in the linked template you must call the variable including the root and any sub variables like parameters(‘machineSettings’).vmSize

Linked or nested templates provide a great deal of flexibility to templates where making a new linked template for a custom extension or to deploy X number of Virtual Machines.

Until the next time! Happy Template Making!

Tim Day