Saving Passwords for Add-AzureAccount

One of the great features of the recent versions of Azure PowerShell is a non-interactive option for the Add-AzureAccount cmdlet. Unfortunately, the instructions tell you to save your Azure password in plain text, but there are much more secure alternatives. I explain one in this post.

——————-

As users of Azure PowerShell know well, there have always been two distinct ways of making your Azure account available to Windows PowerShell. You can download (Get-AzurePublishSettingsFile) and import (Import-AzurePublishSettingsFile) a PublishSettings file. This technique uses a management certificate with security credentials and, while it’s a bit more complex, once the certificate is on the machine, you can access your Azure account in Windows PowerShell.

You can also use Azure Active Directory (Azure AD). The Add-AzureAccount cmdlet prompts you to sign into your Azure account by popping up a sign-in window. When sign-in succeeds, information about your Azure account is saved in a subscription data file in your roaming user profile and Windows PowerShell gets an access token that it can use to access your Azure account on your behalf. This is a great strategy, except that the token expires (in about 12 hours) and the interactive sign-in prompt prevents you from using it in a script.

Until now.

Beginning in Azure PowerShell 0.8.9, you can use the Credential parameter of Add-AzureAccount to suppress the sign-in pop-up. It works only with an organizational ID (not with a Microsoft account), but it’s easy to create an organizational ID for any account. More on that below).

Here’s the snippet for adding an Azure account to Windows PowerShell in a script. As an alternative to the equally interactive Get-Credential cmdlet, you use the New-Object cmdlet to create a PSCredential object. Then, you pass it the username and a secure string form of the password of your Azure account. When you call Add-AzureAccount with the PSCredential object, it uses the credentials to sign you in so you are not prompted.

$cred = New-Object -TypeName System.Management.Automation.PSCredential ($userName, $securePassword)
Add-AzureAccount -Credential $cred

This is a great solution, but the instructions in How to install and configure Azure PowerShell tell you to use plain text for both the user name and password.

$username = "<your_organizational_account_user_name>"
$securePassword = ConvertTo-SecureString `
        -String "<your_organizational_account_password>" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential ($username, $securePassword)
Add-AzureAccount -Credential $cred

This is neither secure nor necessary. Although no method is completely secure, storing a password in plain text in a text/script file on disk is downright scary. If you need to save a password on disk, at least save it in an encrypted string.

It’s easy to do. In this code, we use the Read-Host cmdlet to prompt you for the password (just once). The AsSecureString parameter is equivalent to piping the password string that you type to the ConvertTo-SecureString cmdlet. The result is a secure string.

$secure = Read-Host -AsSecureString -Prompt "Enter your Azure organization ID password."

Next, use the ConvertFrom-SecureString cmdlet to convert the secure string to an encrypted string and then save it to disk.

ConvertFrom-SecureString -SecureString $secure | Out-File -FilePath $FilePath

If anyone happened to peek in that file, they’d see something that looks like this.

01000000d08c9ddf0115d1118c7a00c04fc297eb010000009b2299cb1e643949ae2af8e01153829c00000
00001000000d08c9ddf0115d1118c7a00c04fc297eb010000009b2299cb1e643949ae2af8e01153829c00
000000020000000000106600000001000020000000e5e552e0bc6def08bf715a2511ad26cef2a41211f28
35cba161944b4f17fc017000000000e80000000020000200000008b267e1ac697b27b381925dc4cc43db6
a06c6f5524442e340e7b456fb9005a42200000007c829e84ebd387a803b10ca08d0c43c0df7abbc2e1067
07ad21178d0b1f215084000000093ae66ef19b086d52da13b76308ee7f4910d7b70c5af1c8366db5f8be1
c746c301eb88c11e4609ad4ef90a638adba7c571b739978952c165626075282e58eec6

Then, in Azure PowerShell scripts, you use almost the same code for your Add-AzureAccount command, except that you add a Get-Content command to get the encrypted string from its file.

$username = "coadmin@myenterprise.onmicrosoft.com"
$securePassword = ConvertTo-SecureString (Get-Content -Path $FilePath)
$cred = New-Object -TypeName System.Management.Automation.PSCredential ($username, $securePassword)
$result = Add-AzureAccount -Credential $cred

This is easy and much more secure. Here’s a little function that saves any password to disk as an encrypted string.

    function Save-Password
    {
        Param
        (
            [parameter(Mandatory = $true)]
            [String]
            $FilePath,
            
            [parameter(Mandatory = $true)]
            [Switch]
            $PassThru
        )
        
        $secure = Read-Host -AsSecureString "Enter your Azure organization ID password."
        $encrypted = ConvertFrom-SecureString -SecureString $secure
        $result = Set-Content -Path $FilePath -Value $encrypted -PassThru
        
        if (!$result)
        {
            throw "Failed to store encrypted string at $FilePath."
        }
        if ($PassThru)
        {
            dir $FilePath
        }
    }

 

Now, about that organizational ID. You can create at least one organizational ID for any Azure account, even one that is secured with a Microsoft account, such as an Outlook.com account. You can find the instructions in the “Use the Azure AD method” section of How to install and configure Azure PowerShell.

I still haven’t figured out a workaround for the expiring Azure AD token, so I include an Add-AzureAccount command that gets a new token in every script. But the password is saved as an encrypted string and the user of the script is not interrupted.

June Blender is a technology evangelist at SAPIEN Technologies, Inc. You can reach her at juneb@sapien.com or follow her on Twitter at @juneb_get_help.