Handling passwords with Azure Automation service accounts
Handle the service account password in Azure Automation.
September 10, 2015
Q. What is the best way to handle the password for an Azure Automation credential asset?
A. When using Azure Automation it is often required to connect to Azure subscriptions which requires an Azure AD credential to be used. As a best practice this credential should be dedicated to automation in a similar fashion to service accounts in Active Directory on-premises however by default Azure AD accounts must have their passwords changed every 90 days. There are a number of options to solve this.
The first option would be to configure the password to never expire which is a technique common for on-premises service accounts however this represents a potential security risk. http://windowsitpro.com/azure/configure-azure-ad-passwords-never-expire documents this approach.
A better option is to implement a process to automatically update the Azure AD account password and the credential in a similar fashion to how Managed Service Accounts (MSAs) work in Active Directory. I initially created something that would run on-premises in preparation for a process that would actually run in Azure Automation. This process used the Azure AD cmdlets and the sign-in assistant which is shown below. Note to avoid having to enter a credential it stores the actual password in an unencrypted form which is not desirable but my intention was to make it encrypted when I moved the process to Azure Automation. Note a variable asset must exist containing the subscription name (SubName), a credential asset (MyCred) that will be updated and an unencrypted string asset to store the password (MyCredPassword).
#The automation account is a co-admin and a global admin of the AD so it can change password. Could limit$AutomationAccountName = 'SavAutomationEastUS2'$SubName = Get-AzureAutomationVariable -AutomationAccountName $AutomationAccountName -Name 'SubName'$AutoCred = Get-AzureAutomationCredential -AutomationAccountName $AutomationAccountName -Name MyCred#Generate a new password$randomObj = New-Object System.Random$NewPassword=""1..16 | ForEach { $NewPassword = $NewPassword + [char]$randomObj.next(33,126) }$NewPassword#Create credential to connected to Azure AD$user = $autocred.UserName$pworig = (Get-AzureAutomationVariable -Name MyCredPassword -AutomationAccountName $AutomationAccountName).Value$pw = ConvertTo-SecureString $pworig -AsPlainText -Force$AzureADCredential = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $user, $pwConnect-MsolService -Credential $AzureADCredentialSet-MsolUserPassword –UserPrincipalName [email protected] –NewPassword $NewPassword -ForceChangePassword $false$user = $autocred.UserName$pw = ConvertTo-SecureString $NewPassword -AsPlainText -Force$cred = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $user, $pwSet-AzureAutomationCredential -Value $cred -Name $AutoCred.Name -AutomationAccountName $AutoCred.AutomationAccountName#Save password right now in case we need it. What about encrypt. Assume will decryptSet-AzureAutomationVariable -AutomationAccountName $AutomationAccountName -Name MyCredPassword -Value $NewPassword -Encrypted $false
To move to Azure Automation I had to make a change because the sign-in assistant is not available which is required to use the Azure AD cmdlets. I therefore changed the code to use some cmdlets that leverage the Graph API. Additionally the code to create a random password had to be modified as the existing random password code did not work in Azure Automation. Below is the Azure Automation code I created which you can then schedule to run weekly which will create a new password. Additionally the stored password (required to call the Graph API) is stored encrypted.
workflow UpdateAutomationAccount{ #The automation account is a co-admin and a global admin of the AD so it can change password. Could limit $AutomationAccountName = 'SavAutomationEastUS2' # Azure AD domain to authenticate against $AzureADDomain = Get-AutomationVariable -Name 'AzureADDomain' #Get the subscription name $SubName = Get-AutomationVariable -Name 'SubName' $MyCred = Get-AutomationPSCredential -Name 'MyCred' $pworig = $MyCred.GetNetworkCredential().Password Add-AzureAccount -Credential $MyCred Select-AzureSubscription -SubscriptionName $SubName $AutoCred = Get-AzureAutomationCredential -AutomationAccountName $AutomationAccountName -Name 'MyCred' $AutoUser = $AutoCred.UserName #Generate a new password that is 16 characters with at least 2 special $NewPassword = InlineScript { #Load "System.Web" assembly in PowerShell console Add-Type -AssemblyName System.Web #Calling GeneratePassword Method [System.Web.Security.Membership]::GeneratePassword(16,2) }#Get string ready for JSON which fixes certain characters $JSONNewPassword = ConvertTo-Json $NewPassword#Connect using Graph API which needs modules from https://github.com/tiander/OMSsearchAPI $APIVersion = "1.5" $AppIdURI = "https://graph.windows.net" # Set up connection object to pass into Invoke-AzureADMethod $ADConnection = @{"Username"=$AutoUser;"AzureADDomain"=$AzureADDomain;"Password"=$pworig;"APPIdURI"=$AppIdURI;"APIVersion"=$APIVersion} $URI = "https://graph.windows.net/$AzureADDomain/users/$AutoUser" $Body = @"{ "passwordProfile": { "password": $JSONNewPassword, "forceChangePasswordNextLogin": false }}"@ #Update the Azure AD account password $UserUpdate = Invoke-AzureADMethod -URI $URI -Connection $ADConnection -Body $Body -Method PATCH #Create updated credential object for account with new password $NewSecurePassword = ConvertTo-SecureString $NewPassword -AsPlainText -Force $cred = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $AutoUser, $NewSecurePassword #Update the automation credential object with new password Set-AzureAutomationCredential -Value $cred -Name $AutoCred.Name -AutomationAccountName $AutoCred.AutomationAccountName }
To use this code you must perform the following:
Import the two Graph API modules from https://github.com/tiander/OMSsearchAPI into the Automation account
You need the following assets created in the automation account:
MyCred – Credential asset which is configured with the current automation account username and password and is the account that have its password updated
SubName – String asset containing name of the Azure subscription
AzureADDomain – String asset containing name of Azure AD instance to which the account belongs toThe automation account will likely need to be a co-admin to perform its duties from runbooks and have the permission to change passwords in Azure AD
Paste the above code into a runbook and change the automation account name at the start of the script. It can also be downloaded from the TechNet Gallery here which is where I'll keep it updated.
Test the runbook by running as a test
Schedule the runbook to run weekly
About the Author
You May Also Like