I work on Azure Tenants that utilize multiple subscriptions in their design. I wanted to centralize my Azure Automation work and use a single Automation account. By default, I found that powershell scripts I fired off from Azure Automation work within the subscription that the Automation account was created within. But business requirements necessitate multiple subscriptions and MY requirements necessitate using a single Automation Account to simplify my life (and the lives of everyone else that I work with). A running joke is that, when it comes to IT, well-intention’d laziness is a virtue… We rebrand laziness as “simplicity,” “automation,” and/or “efficiency,” depending on the context of the conversation of course. I often say somewhat tongue-n-cheek that “you don’t want your IT department to be “busy” all the time.” An all-the-time overly busy IT department typically means that something was poorly planned and/or your network is being held together with spit and frayed ethernet cable. Anyhow, I digress…
With that groundwork laid, the goal is a Powershell automation script that can essentially “hop” subscriptions as needed. I also value modularity. Goodness knows that in the pursuit of laziness we should never do the same work twice except in the most extreme or dire circumstances. To that end, I wrote a simple function I could just drop into any script along with an additional parameter and now said script can be used across subscriptions…
That parameter + function looks like this:
[Parameter (Mandatory = $false)]
[String] $SubscriptionName,
)
Function Use-Subscription ($SubscriptionName) {
$DefaultSubscription = Get-AzContext | Select-Object -ExpandProperty Subscription | Select-Object -ExpandProperty Name
$SubscriptionList = Get-AzSubscription | Select-Object -ExpandProperty Name
If (!$SubscriptionName) {
Write-Output ""
Write-Output "Subscription parameter left blank, using the subscription of the Azure Automation Account: $DefaultSubscription"
Return
}
If (!$SubscriptionList.Contains($SubscriptionName)) {
Write-Output ""
Write-Output "Specified Subscription not found in list of Subscriptions available to runbook account, check spelling and ensure Runbook RunAs account has necessary permissions. Cancelling Operation"
Exit
}
Else {
Select-AzSubscription $SubscriptionName
Write-Output ""
Write-Output "Selected subscription $SubscriptionName"
Return
}
}
Give your Azure Automation RunAs Account Privileges on other Subscriptions
In a previous post I talked about using an Azure Automation “RunAs” account to simplify credential management and access for Azure Automation scripts. There is one additional thing that must be done if using the Azure Automation RunAS account. The RunAS account by default is granted the “contributor” role on the subscription that the Azure Automation Account resides in. It needs permissions on the other subscriptions in your Azure tenant where you also wish it to perform work. You can handle this however you like… if you use Management Groups to organize your subscriptions, more power to you, you may only need to give the account permissions in a single place. Otherwise, you need to go to each subscription and assign the account privileges. To get the identity of said RunAs account, navigate to your Azure Automation Account –> Under “account settings” click “Run as accounts” –> click on “Azure Run As Account” –> copy the “display name” to your clipboard… This is the Azure AD identity you want to give privileges on your different subscriptions.
The Function
I, like most people, appreciate when things don’t break or do the unexpected. While the above function could probably be significantly shorter, I wanted to add some “safety” logic for handling admin fat-fingering (which I am, *cough* prone to do from time to time). I will quickly walk-through pieces of the function. First… I get the default subscription name and save that to a variable. This is the subscription that the Azure Automation Account lives in and works in by default. Next, I get a list of all of the Subscriptions that are visible to the Azure Automation RunAs account and save that to an array. Then I run a few tests against the parameter value that was supplied when the script is initiated. First, if the parameter is left empty… fine; we will try things on the default subscription. Next, if the parameter value is supplied -but- the provided value doesn’t exist on the list of subscriptions visible to the RunAS account, then we gracefully exit and give an explanation message back.
After those checks have been passed… the function logs the running script into the specified subscription and we have successfully hopped the “subscription fence” and can automate anywhere we please…
Conclusion
Laziness Efficiency achieved! Drop this function and parameter into your powershell scripts and centralize your work!