PowerShell scheduled job - Connect-AzureAD using stored/encrypted credentials

Hi, I have to create PowerShell scheduled job which does the following:

  1. Searches for disabled user accounts log entries (security logs) and stores disablement date into info AD attribute of disabled user account object (moves account to Pending Deletion OU as well).
  2. Checks if disablement date of already disabled user accounts is 30 days before current date - if yes it deletes user accounts altogether and sends email to disabled users managers.
This is of course very trivial but there is a gotcha. We have multiple forests completely isolated (do not ask me why - security team is better address) with IT staff having accounts in each forest. We have our main forest synced with Azure AD so up to date value for disabled user manager should be pulled from Azure AD and with that its email to send notification to.

What do you suggest for Connect-AzureAD within a script - we have dedicated account for this purpose (no MFA) but I want to avoid plain text at any cost in script body and also allowing script to connect automatically using that account.

Well, this gets a little complicated.
The typical solution is to persist to disk (save) the pwd as secure string (see the code of Get-SBCredential of the AZSBTools PS module).
So, you’d manually invoke

$Cred = Get-SBCredntial -UserName myAzureServicePrincipalName -Refresh -CredPath c:\folder

This will prompt the user to manually enter the secret/pwd, and saves it in encrypted form to a file in the provided folder.
In your production script you retrieve and use the credential by invoking:

$Cred = Get-SBCredntial -UserName myAzureServicePrincipalName -CredPath c:\folder

The complication here is that if this is part of a scheduled tasks that runs under a different user other than than the user who invoked the first command (with the -Refresh option), the second command won’t work because the user credential is what’s used to decrypt the secure string.

I can think of a couple ways to overcome this difficulty:

  1. Run the first command above with the refresh option under the scheduled task service account (Start-Process … -Credential …)
  2. Specify what to use to encrypt the secure string with in step 1 instead of the default current user credential. Currently Get-SBCredential does not support using other than the default current user credential to encrypt the pwd, although the underlying Cmdlets do. To that end, I’m working on a function that would use a non-exportable certificate on the computer where the script is invoked to encrypt the pwd of the Azure or other needed accounts, so that the Azure credential is tied to the machine and not to the user invoking the scheduled script…

I managed to accomplish this using CredentialsManager PowerShell module - not certain how secure this is but better than having plain text anywhere in the script body. If this is risky I would like to know what else is at my disposal.

New-StoredCredential -UserName user@xyz.onmicrosoft.com -Password "SomePasswordHere"
$cred = Get-StoredCredential -Target ServerName
Connect-AzureAD -Credential $cred

One thing is bothering me here, scheduled task running under dedicated domain account won’t be able to connect to Azure AD using account above created using my domain admin account? It looks I have to create account (credential) in Credentials Manager with commands above but from PS session run under account scheduled task will run under.

You have the same exact problem: password is encrypted with the logged on user credential. So running the automation as a scheduled task running under a service account will not work.

So not pretty workaround would be logging in once using account scheduled task will run under to create credential in Credential Manager. After that I could log in using my domain account and scheduled task will be able to decrypt credential used to connect to Azure AD.

Well, a service account by definition is an account that does not have the Windows ‘Log on interactively’ right… :slight_smile:

Of course, that’s why I said not pretty. :slight_smile:

You could encrypt it with a specific AES key and then save/protect that. Your script can retrieve the key, decrypt the password, then profit.