Domain join Azure VMs from ARM template with Key Vault secured credentials – Part 1

This will be a three part blog series on Automatically domain join Azure VMs from ARM template deployment with Key Vault secured domain join credentials

  • 1: Prerequisites and Key Vault
  • 2: ARM Template and JsonADDomainExtension, details
  • 3: Summary, Thoughts and flaws

Prerequisites and Key Vault.


When using ARM templates to automate provisioning of VMs you will need to domain join the VMs eventually. There are several ways of doing this, the three most common ones i have seen are all based on extensions on the Azure VM.

  • JsonADDomainExtension
  • CustomScriptExtension
  • DSC

The result is the same, VM is domain joined, but the effort, management and operations for these three methods are very different.

For this post i will focus on JsonADDomainExtension directly in ARM template, with fetching credentials for domain joining from Keyvault.

We leverage keyvault because we do not want to expose the credentials in a template! (This i write some more about in a part 3…)

Extensions

There are several posts about this on the web but in general i think the documentation around this is lacking. You do not get to much info about the extension and how they work in the backend, i will point out what i mean in this post. I tried to do a deeper dive into this about 2 years ago while doing some activities with it. Got things working and have worked since, recently i had the need to revisit this again and experience the same lack of documentation.

But also to be fair, currently there are 1189 extension if i look in “West Europe”. That is alot to document, most are versions but still many to document.

The JsonADDomanExtension exist in three versions (What is different in these versions?)

Some prerequisites to point out for the Extension and the Keyvault combo to work, list for quick check and details follows below.

  • OU Path cannot be the default Computers
  • ARM template needs secrets passed in as parameters
  • Keyvault needs to allow ARM engine to read the secrets
  • User/ServicePrincipal (the one deploying the ARM template) must have “Microsoft.KeyVault/vaults/deploy/action” permission
  • Username in Keyvault needs to be in format “domainName\userName” (not anymore)

OU Path cannot be the default Computers

Commonly you tend not have the default OU as landing zone for new computer objects, but this is something that i would have liked to be able to read from a documentation on the extensions. So make sure you have another OU ready for the domain joining, i have one called AzureVM

The error messages you get when deploying the ARM does not hint you about Computers not beeing a valid OU. You need to find the log on the server to figure this out, the log is actually great to know where to find for any extension troubleshooting.

ARM template needs secrets passed in as parameters

Parameter File

This is a small pain at the moment, that you need to reference the secrets from keyvault, resulting in needing a parameter or linked/nested template.

A pain because depending on how you deploy your template you might want to keep the deployment in a single template for that resource.

Many customer have a cloud management portal on top of clouds (Azure, AWS, GCP etc) and building ARM templates that these portals initiate is common. So you need to run the template directly not using a parameter file.

But just having a Parameters file is easy enough you can manage.

Linked/Nested Template

In the cases when you have an additional tool for provisioning like a Portal or some ITSM like ServiceNow you need to deploy the actual template and not the parameter file.

You could in many scenarios just have a PowerShell script called from the portal or ITSM that would run the Parameter file and the template, but in most cases i have encountered this has not been an option.

So linked (or nested) template is the option here

This is an excellent post on multiple ways to pass secrets to ARM Templates: https://devkimchi.com/2019/04/24/6-ways-passing-secrets-to-arm-templates/  thanks to @devkimchi

Keyvault needs to allow ARM engine to read the secrets

Have the “enabledForTemplateDeployment” property enabled on the keyvault. This property must be true before the template deployment process can access the secrets that are defined in the key vault.

User/ServicePrincipal

(the one deploying the ARM template) must have “Microsoft.KeyVault/vaults/deploy/action” permission

If you are the Owner or Contributor you have the access and can assing access to potential Service Principal or similar, but you can create a custom role definition and assign only the “Microsoft.KeyVault/vaults/deploy/action” permissions.

https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-keyvault-parameter#grant-access-to-the-secrets

Important

If a user has Contributor permissions to a key vault management plane, the user can grant themselves access to the data plane by setting a Key Vault access policy. You should tightly control who has Contributor role access to your key vaults. Ensure that only authorized persons can access and manage your key vaults, keys, secrets, and certificates.

Important

Key Vault access policies apply at the vault level. When a user is granted permission to create and delete keys, they can perform those operations on all keys in that key vault.

Important

If a user has Contributor permissions to a key vault management plane, the user can grant themselves access to the data plane by setting a Key Vault access policy. You should tightly control who has Contributor role access to your key vaults. Ensure that only authorized persons can access and manage your key vaults, keys, secrets, and certificates.

Read this too understand the Access model with  Data plan and management plane for Keyvault.

https://docs.microsoft.com/en-us/azure/key-vault/key-vault-secure-your-key-vault#data-plane-and-access-policies

Read how to setup KeyVault here

https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-manager-tutorial-use-key-vault#prepare-a-key-vault

Secure your Keyvault

https://docs.microsoft.com/en-us/azure/key-vault/key-vault-secure-your-key-vault

Additional Links to read

3 thoughts on “Domain join Azure VMs from ARM template with Key Vault secured credentials – Part 1

  1. You have a very nice and informative blog here. In any case, I manage to deploy on VMs and to join existing VMs to domain.
    Only I can’t manage to merge this process, so that a VM is automatically deployed via an ARM template and joined to on-prem domain in the same template. I have already set something up in KeyVault to be allowed to join with that account, but the template is not good somewhere. I hope you can help with this?

Leave a Comment