Logging on to Azure for your everyday job

Sometimes life is about the little things, and one little thing that has been bothering me is logging on to Azure RM in Powershell using Add-AzureRMAccount. Every time you start Powershell, you need to log on again and that gets tired quickly, especially with accounts having mandatory 2FA.

It gets even more complicated if you have multiple accounts to manage, for instance, one for testing and another for production. To top it off, you can start over when it turns out that your context has expired, which you will only discover after you actually executed some AzureRM commands.

The standard trick to make this easier is to save your Azure RM context with account and subscription information to a file (Save-AzureRMContext), and to import this file whenever you need (Import-AzureRMContext). But we can do a little bit better than that.

Here is my solution to the problem.

  • Use a PowerShell profile to define a function doing the work. A profile gets loaded whenever you start PowerShell. There are multiple profiles, but the one I want is for CurrentUser - Allhosts.
  • The function will load the AzureRM context from a file. If there is no such file, it should prompt me to log on.
  • After logging on, the context should be tested for validity because the token may have expired.
  • If the token is expired, prompt for logon again.
  • If needed, save the new context to a file.

So here is my take on it. Note the specific naming convention that I use for functions defined in a profile.

 function profile_logon_azure ([string] $parentfolder, [string]$accountname)
{
    $validlogon = $false
    $contextfile = Join-Path $parentfolder "$accountname.json"
    if (-not (Test-Path $contextfile))
    {
        Write-Host "No existing Azure Context file in '$parentfolder', please log on now for account '$accountname'." -ForegroundColor Yellow
    } else {
        $context = Import-AzureRmContext $contextfile -ErrorAction stop
        #
        # check for token expiration by executing an Azure RM command that should always succeed.
        #
        Write-Host "Imported AzureRM context for account '$accountname', now checking for validity of the token." -ForegroundColor Yellow
        $validlogon = (Get-AzureRmSubscription -SubscriptionName $context.Context.Subscription.Name -ErrorAction SilentlyContinue) -ne $null
        if ($validlogon) {
            Write-Host "Imported AzureRM context '$contextfile', current subscription is: $($context.Context.Subscription.Name)" -ForegroundColor Yellow
        } else {
            Write-Host "Logon for account '$accountname' has expired, please log on again." -ForegroundColor Yellow
        }
    }
    if (-not $validlogon)
    {
        $account = $null
        $account = Add-AzureRmAccount
        if ($account) 
        {
            Save-AzureRmContext -Path $contextfile -Force
            Write-Host "logged on successfully, context saved to $contextfile." -ForegroundColor Yellow
        } else {
            Write-Host "log on to AzureRM for account '$accountname' failed, please retry." -ForegroundColor Yellow
        }
    }
}

To make this work, add this function to the powershell profile: from the Powershell ISE, type ise $profile.CurrentUserAllHosts to edit the profile and copy/paste the function definition.

Suppose I have two Azure RM accounts that I want to use here, called 'foo' and 'bar'. For that I would add the following function definitions to the profile:

 #
# specific azure logons. Context file is deliberately in a non-synced folder for security reasons.
#
function azure-foo { profile_logon_azure -parentfolder $env:LOCALAPPDATA -accountname "foo" }
function azure-bar { profile_logon_azure -parentfolder $env:LOCALAPPDATA -accountname "bar" }

To log on to 'foo', I'd simply execute azure-foo. If this is a first logon, I get the usual AzureRM logon dialog and the resulting context gets saved. The next time, the existing file is loaded and the context tested for validity. From that point on you can switch between accounts whenever you need.

Try it, it just might make your life a little bit easier.