Using Azure Automation with Multiple Tenants

This post has been republished via RSS; it originally appeared at: New blog articles in Microsoft Tech Community.

Welcome to a tale from the lab of Jon Warnken a Premier Field Engineer. 

 

I have been working with Azure Automation recently,  had a need for a runbook that required access in two different Azure Tenants. Because I had a virtual machine in one tenant (Tenant1) that is using a dynamic public IP address that is being used in a DNS zone record in another tenant (Tenant2), I need to update the DNS record when the ip address changes. Now if the VM was in the same tenant as the dns zone this would be easy by making an alias record and map it to the public IP of the VM.

A quick search found a couple of existing runbooks that work with in the same tenant. After updating the code to use parameters and the Az modules this is runbook code I am using:

 

 

 

 

Param( [Parameter(Mandatory=$true)] [String]$RunAsAccount = "AzureRunAsConnection", [Parameter(Mandatory=$true)] [String]$SubscriptionId1, [Parameter(Mandatory=$true)] [String]$SubscriptionId2, [Parameter(Mandatory=$true)] [String]$vmresourcegroup, [Parameter(Mandatory=$true)] [String]$vmipname, [Parameter(Mandatory=$true)] [String]$DNSrecord, [Parameter(Mandatory=$true)] [String]$DNSzone, [Parameter(Mandatory=$true)] [String]$DNSresourcegroup, [Parameter(Mandatory=$true)] [String]$DNSrecordName ) $connectionName = $RunAsAccount $servicePrincipalConnection = Get-AutomationConnection -Name $connectionName Connect-AzAccount -ServicePrincipal -TenantId $servicePrincipalConnection.TenantId -ApplicationId $servicePrincipalConnection.ApplicationId -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint | out-null Write-Output "Connecting to subscription: $SubscriptionId1" Select-AzSubscription -SubscriptionId $SubscriptionId1 | out-null $VMIP = (Get-AzPublicIpAddress -ResourceGroupName $vmresourcegroup -Name $vmipname).IpAddress Write-Output "VM Public Ip is $VMIP" $DynDNS = $DNSrecord #Get IP based on the Domain Name [string]$MyDynamicIP = ([System.Net.DNS]::GetHostAddresses($DynDNS)).IPAddressToString Write-Output "$DynDNS resolves to $MyDynamicIP" If($VMIP -ne $MyDynamicIP){ Write-Output "Connecting to subscription: $SubscriptionId2" Select-AzSubscription -SubscriptionId $SubscriptionId2 | out-null $zone = Get-AzDnsZone -Name $DNSzone -ResourceGroupName $DNSresourcegroup $dnsrs = Get-AzDnsRecordSet -Zone $zone -Name $DNSrecordName -RecordType A $DNSIP = (Get-AzDnsRecordSet -Zone $zone -Name $DNSrecordName -RecordType A).Records.Ipv4Address Remove-AzDnsRecordConfig -RecordSet $dnsrs -Ipv4Address $DNSIP Add-AzDnsRecordConfig -RecordSet $dnsrs -Ipv4Address $VMIP Set-AzDnsRecordSet -RecordSet $dnsrs }

 

 

 

 

 

If you would like to use this runbook, you will find it published on the PowerShell Gallery and can be imported into your automation account.

Up to this point I have been testing with in the same tenant and everything was working great. Because my automation account does not have any access in the other tenant, when I use a subscription id in Tenant2 the runbook will fail. Now I had to figure out how to authenticate this runbook in my second tenant. I considered three different options:

1 – Create an account in Tenant2; store the password in a key vault in Tenant1; have the runbook retrieve the password and use it to authenticate when needed for actions in Tenant2.

2 – Create an account in Tenant1; add the account as a guest user in Tenant2; use the account to execute the runbook.

3 – Delegate the automation account’s run as account in Tenant 2. 

 

Option 1 worked when manually testing the code but ran into context and timing issues when executing via the automation account. This approach also has security and operational risks that would not make it acceptable for a production environment.

Option 2 worked when manually testing but still failed when executing in the context of the automation account.

The manual testing of the other options showed that it was possible to do automate this. It just needed to be delegated correctly. Enter Azure Lighthouse, this is how partners provide managed services in Azure. But the functionality can also be used by enterprises with multiple tenants. I decided to onboard via an Azure Resource Manager template. The process and sample template are available at https://docs.microsoft.com/en-us/azure/lighthouse/how-to/onboard-customer.

The only challenge I had was getting the principal id for my automation run as account. The run as account exists as an application and a managed application in Azure Active Directory. If you go the portal and look up the application you will see the Managed application instance.

 

image.png

  

  Clicking on that link will allow you to discover the correct object id to use with your ARM template.

 

Armed this and the role id you want to delegate complete the parameter json file and onboard the delegation in the target tenant. I used the resource group delegation template option

 

And setup the parameter file to delegate a user with owner access and my automation account with dns zone contributor access.

 

 

 

{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { "mspOfferName": { "value": "Fabrikam Managed Services - MrBoDean" }, "rgName": { "value": "Your resource group name" }, "mspOfferDescription": { "value": "Fabrikam Managed Services - MrBoDean" }, "managedByTenantId": { "value": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }, "authorizations": { "value": [ { "principalId": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy", "roleDefinitionId": "8e3af657-a8ff-443c-a75c-2fe8c4bcb635", "principalIdDisplayName": "Your User Name" }, { "principalId": "cccccccc-cccc-cccc-cccc-cccccccccccc", "roleDefinitionId": "befefa01-2a29-4197-83a8-272ff33ce314", "principalIdDisplayName": "Your Automation Account User" } ] } } }

 

 

 

Now this runbook can check and update the DNS record in the remote tenant.

 

Hopefully you find this useful and happy automating.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.