Reusing Azure Automation Run As Accounts
TL;DR – To copy a Run As account to a different Automation Account, run this script in your source Automation Account.
As a solution architect, I work with a lot of enterprise customers. It’s interesting and challenging, but every so often (oh who am I kidding…ALL the time) I get asked some off-the wall questions. This time it was how to use the same Run As account across multiple Azure Automation accounts.
Why would you ever need to do this? Well, in this case the organization had locked down Application Registrations in Azure AD. So in order to have Azure Automation automatically provision a Run As account, the user also needed fairly hefty AAD privileges. Why would an organization ever want to lock that down? Hey…one problem at a time. Bottom line, the organization already had a Run As account setup and they wanted to just reuse it in other Automation Accounts. Ok…let’s get started.
Why is this harder that it should be?
Azure makes it super easy to create a new Run As account as part of the overall Automation Account setup. It’s just a simple Yes/No toggle. When you select ‘Yes’ Azure registers an Application/Service Principal in Azure AD, assigns subscription permissions to the SPN, and adds a Connection and Certificate to the Automation Account. Pretty good for just clicking ‘Yes’.
To use the same Run As account in another Automation Account you just need to copy the Connection and Certificate from the source to the target account. Easy right? Ha! If you drill into the Connection information in the Automation Account, you can see that it is all text. You can manually create a Connection in your target Automation Account and just copy/paste the information over.
The Solution
We are going to build a PowerShell script to run in a Runbook within our source Automation Account. This script will grab the certificate from the local certificate store, export it, and then copy it to the target Automation Account along with creating a connection.
The first part is pretty easy, using the SPN connection in the source we grab the certificate thumbprint. We can then use this to locate the actual certificate in the local certificate store (Cert:\CurrentUser\My):
[ps]### Loading local certificate
Write-Output "Getting Local Certificate..."
$thumbprint = $servicePrincipalConnection.CertificateThumbprint
$cert = Get-ChildItem -Path Cert:\CurrentUser\My | where {$_.Thumbprint -match $thumbprint}
Write-Output $cert[/ps]
Now that we have the cert, we can export it to a local file. The export process requires a password to protect the certificate since it is being stored on disk. The password is only a temporary password used for the export/import and is not part of the certificate itself. Once you upload the certificate into the target Automation Account you do not need to keep the password.
[ps]### Exporting local certificate
$certFile = ($env:TEMP) + $certFile
Write-Output "Exporting Certificate to File: $certFile"
$certPassword = ConvertTo-SecureString -String $certPassword -Force -AsPlainText
[system.IO.file]::WriteAllBytes($certFile, ($cert.Export('PFX', $certPassword)))[/ps]
The last bit is to use the New-AzureRmAutomationCertificate and New-AzureRmAutomationConnection commands to push information over to the target account. The Connection information is just pulled dynamically from the source account.
[ps]### Copying local certificate to target automation account
if(Test-Path $certFile){
Write-Output "Certificate Successfully Exported"
Write-Output "Importing Certificate..."
New-AzureRmAutomationCertificate -ResourceGroupName $targetResourceGroup -AutomationAccountName $targetAutomationAccount -Name $certName -Path $certFile -Exportable -Password $certPassword
Write-Output "Import Complete"
Write-Output "Creating Connection..."
$connectionFieldValues = @{"ApplicationId" = $servicePrincipalConnection.ApplicationId; "TenantId" = $servicePrincipalConnection.TenantId; "CertificateThumbprint" = $thumbprint; "SubscriptionId" = (Get-AzureRmContext).Subscription.Id}
New-AzureRmAutomationConnection -ResourceGroupName $targetResourceGroup -AutomationAccountName $targetAutomationAccount -Name $connName -ConnectionTypeName $connType -ConnectionFieldValues $connectionFieldValues
Write-Output "Connection Created"
} else {
Write-Output "Certificate Export Failed"
}[/ps]
Wrap-Up
The full PowerShell script can be found here: https://github.com/wagesworld/copy-AzureRunAs
Simply create a new PowerShell Runbook in your source Automation Account. Drop in the script code and update the target Resource Group & Automation Account name. Then run it. If you are in the portal UI you can just hop over to the Test Pane to run it.
Once it runs you should be able to go to your target Automation Account and under Account Settings click ‘Run as accounts’ to see your connected Run As accounts.
WARNING: Reusing Run As accounts in this manner can cause some unwanted behaviors. Behind the scenes Automation Accounts are tied to their Run As accounts. If you delete an Automation Account, Azure will attempt to clean up any associated Run As accounts – i.e. the Run As application/SPN in Azure AD will also be deleted. So deleting an Automation Account will break any other connected Automation Accounts that are using the same Run As account.
Comments
- Anonymous
February 17, 2018
great solution, thanks for sharing!