Working with PowerShell & Multiple Azure Contexts
When working with multiple Azure subscriptions, the PowerShell Az.* modules allow for easy context switching. This
means that you can run commands agains multiple subscriptions, or you can run commands against subscriptions without
changing your default context.
An Azure Context object contains information about the Account that was used to sign into Azure,
the active (for that context) Azure Subscription, and an auth token cache is not actually empty,
it just can't read from here for security reasons, though you can read it with the Get-AzAccessToken command.
Here's what is in an Azure Context object:
Now that $AzContext variable can be used with any Az PowerShell command or function, to force a command to be run within that context.
Now I can list all the Resource Groups in the TK-PRD subscription, even if my shell has the default context set to the TK-DEV subscription.
You can work this into a foreach loop if you want to do something in multiple subscriptions.
If I want to find all the Recovery Services Vaults in all my subscriptions:
PS> Get-AzContext | fl * Name : TK-PRD (yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy) - tim@timkennedy.net Account : tim@timkennedy.net Environment : AzureCloud Subscription : yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy Tenant : zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz TokenCache : VersionProfile : ExtendedProperties : {}If you just wanted to change the context in your terminal, so that future commands all run against that new subscription, you could just use Set-AzContext to change to any Subscription your account has access to.
Set-AzContext -Subscription 'TK-PRD'or
Get-AzContext -SubscriptionName 'TK-PRD' | Set-AzContextBut, even better, you can set the context per command via the -DefaultProfile argument or its alias -AzContext. This works with all the Az.* PowerShell modules. For example:
$Subscription = 'TK-DEV' $AzContext = Get-AzContext -ListAvailable | ?{$_.Subscription.Name -eq "$Subscription"}
Now that $AzContext variable can be used with any Az PowerShell command or function, to force a command to be run within that context.
Get-AzResourceGroup -DefaultProfile $AzContext
Now I can list all the Resource Groups in the TK-PRD subscription, even if my shell has the default context set to the TK-DEV subscription.
PS> Get-AzContext Name Account SubscriptionName Environm ---- ------- ---------------- -------- TK-DEV (xxxxxxxx-xxxx-xxxx-xxxx-xxxx… tim@tkdev… TK-DEV AzureClo PS> Get-AzContext -DefaultProfile $AzContext Name Account SubscriptionName Environm ---- ------- ---------------- -------- Default tim@tkdev… TK-PRD AzureClo PS> Get-AzResourceGroup -DefaultProfile $AzContext -Location eastus ResourceGroupName : cloud-shell-storage-eastus Location : eastus ProvisioningState : Succeeded Tags : ResourceId : /subscriptions/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy/resourceGroups
You can work this into a foreach loop if you want to do something in multiple subscriptions.
If I want to find all the Recovery Services Vaults in all my subscriptions:
PS> foreach ($c in (Get-AzContext -ListAvailable)) { >> "searching $($c.Subscription.Name)" >> Get-AzRecoveryServicesVault -DefaultProfile $c >> } searching TK-DEV Name : rsvault-dev ID : /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups /dev-rs-rg/providers/Microsoft.RecoveryServices/vaults/rsvault-dev Type : Microsoft.RecoveryServices/vaults Location : useast ResourceGroupName : dev-rs-rg SubscriptionId : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx Properties : Microsoft.Azure.Commands.RecoveryServices.ARSVaultProperties Identity : searching TK-PRD Name : rsvault-prd ID : /subscriptions/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy/resourceGroups /prd-rs-rg/providers/Microsoft.RecoveryServices/vaults/rsvault-prd Type : Microsoft.RecoveryServices/vaults Location : useast ResourceGroupName : prd-rs-rg SubscriptionId : yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy Properties : Microsoft.Azure.Commands.RecoveryServices.ARSVaultProperties Identity :Another advantage of explicitly setting the context you want to work against in your scripts and functions is that you reduct the risk of accidentally running commands against the wrong Subscription when you forget to change your context. I actually keep my default context set to a Subscription that I use only for testing proofs of concept, or for when I'm following along on some kind of training or tutorial. Since everything in that sub is considered ephemeral, this helps protect me from accidental changes to production subscriptions, because of the intent required to change the Azure Context to the subscription I mean to work with. And it is simple to build into scripts and functions:
function Get-SubscriptionAsrVaults { [CmdletBinding()] Param( [Parameter(Mandatory=$true)] [String]$Subscription ) $AzContext = Get-AzContext -ListAvailable | ?{$_.Subscription.Name -eq "$Subscription" } if(!$AzContext) { throw "No Azure Context found for Subscription $Subscription" } $subvaults = Get-AzRecoveryServicesVault -DefaultProfile $AzContext -Ea SilentlyContinue return $subvaults }Now I can iterate through all my subscriptions to find those Recovery Services Vaults. There's an advantage, too when I write scripts to share with other team members, or folks on different teams. I write scripts to automate tasks for the HelpDesk. Requiring the subscription to be specified, then forcing commands to run against the specified subscription. It's not a great protection against human error, but it does increase the risk a little bit.
Comments
Post a Comment