Manipulating Azure AD device objects with PowerShell is something I do often, but one thing I almost always forget to do is connect to Azure before trying to run cmdlets. If you’ve done any PowerShell scripting at all with Azure AD objects, my guess is that you’ve seen, or will soon see in your future, this handy reminder that you forgot to authenticate:
You must call the Connect-AzureAD cmdlet before calling any other cmdlets.
<insert Homer Simpson style Doh! here>
Minor inconvenience just run Connect-AzureAD to log in interactively and you’re back in business. You can even run Connect-AzureAD | Out-Null if you don’t want to clutter up the PowerShell console. But what if you want to run a PowerShell script as a scheduled task? What are the options for silently authenticating for automation purposes?
I was working on a PowerShell script authentication function for just such a scenario and it dawned on me to write this blog. This is something I seldom do and I always forget how I did it without looking back at my previous script examples. So, enjoy the fruit of my forgetfulness with this cheat sheet post that I’ve created as much for me as for you.
There’s probably a million ways to do this, but if you’re not using Azure managed identities, Run As accounts, or some other saved credentials to do your business in the cloud, you’ll need an on-premises solution for things like authentication using scheduled tasks. Here are the options that I usually gravitate around for silently authenticating to Azure AD using PowerShell when interactive logins aren’t feasible:
- Store your username and password in plain text in the script.
- Create and use an encrypted, secure string password file.
Store your username and password in plain text
This is not something I highly recommend doing. In fact, you should never really do this. Even for testing.
That being said, it’s certainly possible and the easiest of all ways to silently authenticate using PowerShell. And sometimes it might actually make sense as long as you’re careful. Maybe you’re just running some quick tests to work out some bugs in a script and get tired of interactively logging in. Besides, you tell yourself, you’ll be sure to delete the script when you’re done because you know how silly it is to store authentication secrets in plain text is. In a scenario such as that, you can just do something like this:
$user = “[email protected]”
$password = “This1sMyP@ssw0rd”
$secPass = ConvertTo-SecureString $password -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential `
($user, $secPass)
Connect-AzureAD -Credential $cred | Out-Null
Be very mindful if you do this, especially since you’ll usually need to provide some high-octane accounts to do advanced scripting in Azure AD. Again, I don’t recommend you do this with any script you’d ever save to re-use later, it’s just a lazy way to quickly get in without having to enter your username and password every time you run a script.
If you tell anyone I told you put your plain text password in a script, I’ll deny it.
Create and use an encrypted, secure string password file
This is my favorite way to securely store passwords for automation purposes. It’s a fairly straightforward process, but there are a few tricks up these commands’ sleeves. I’ll show you the entire script block and then point out some interesting things to know. Here’s the basic idea:
# Create the password file (this should only be done once per computer)
(Get-Credential).Password | ConvertFrom-SecureString | Out-File ` “C:\temp\password.txt”
# Use the password file to authenticate
$user = “[email protected]”
$password = “C:\temp\password.txt”
$myCredential = New-Object –TypeName ` System.Management.Automation.PSCredential `
-ArgumentList $user, (Get-Content $password | ConvertTo-SecureString)
# Silently connect to Azure AD using stored credentials
Connect-AzureAD -Credential $myCredential | Out-Null
Something like so:
How it works
If you’re going to use a text file to store your encrypted password, you’ll usually only need to create the file once. And this is the command to make all the magic happen:
(Get-Credential).Password | ConvertFrom-SecureString | Out-File ` “C:\temp\password.txt”
When you run that, you’ll be prompted to provide the credentials to be stored in the text file at the path that you specify.
The resulting text file hosting your newly encrypted password will look something like this:
You probably don’t want to name the file password.txt as that makes it obvious what’s going. Store the password file somewhere on the computer you used to create the file and reference it in your script.
Remember earlier I said that you usually only need to create a password file once? That’s because there’s an interesting way that the Windows Data Protection API (DPAPI) encrypts data using information from the current user account or computer. DPAPI encrypted password files are only going to work on the computer you create the password file on. I’m not mad, that’s actually kind of great as it adds another layer of security. On the other hand, it can be a little frustrating if you don’t expect that behavior. You’ll get the following error and prompted to interactively log into Azure AD if you move the password file to another computer:
ConvertTo-SecureString : Key not valid for use in specified state.
If you want to create a password file that can be moved around, then you need to modify the command to create the file accordingly by providing a key to use for encryption. If you do that, DPAPI is not used, but rather an AES encryption algorithm is used. I’m not going into that here mostly because I’m lazy, but here’s a good explanation of what I’m talking about if you’re interested in learning more: Example 3: Convert a secure string to an encrypted standard string with a 192-bit key.
And that’s how I use saved credentials with PowerShell scripts. Hope it helps.
You’ve seen my blog; want to follow me on Twitter too? @JeffGilb