Search code examples
azurepowershellazure-automationservice-principalrunbook

In 2021, what is the fastest/easiest way to export the certificate used by an Azure Automation AzureRunAsConnection for local debugging?


As part of troubleshooting/diagnosing a permissions issue with the service principal that one of our runbooks is using, Microsoft support has asked me to run the same PowerShell code locally so we can capture logs. In order to do this, I need to authenticate exactly the same way as the runbook does, which means authenticating with the certificate that the AzureRunAsConnection is using.

After swapping out some cmdlets that only exist in Azure Automation for equivalent commands for Azure RM (e.g. Get-AutomationConnection has to be replaced with Get-AzAutomationAccount and Get-AzAutomationConnection, and you have to switch to using FieldDefinitionValues), the authentication part of my script looks like this::

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$PSDefaultParameterValues['*:ErrorAction']='Stop'

'*** Authenticating with Azure'

$automationAccount = Get-AzAutomationAccount `
  -Name "MY_AUTOMATION_ACCOUNT" `
  -ResourceGroupName "MY_RESOURCE_GROUP"

$connection = $automationAccount | Get-AzAutomationConnection -Name "AzureRunAsConnection"

# Log-in to Az Account Management Graph API (for DNS updates)
Login-AzAccount -ServicePrincipal `
  -Tenant $connection.FieldDefinitionValues.TenantID `
  -ApplicationId $connection.FieldDefinitionValues.ApplicationID `
  -CertificateThumbprint $connection.FieldDefinitionValues.CertificateThumbprint

When I run it, though, I get this error:

Login-AzAccount : No certificate was found in the certificate store with thumbprint
93FAB7F0BA11D08F8ABBAF5C587C77ECB058A8BB

It appears that I need to export the certificate that the AzureRunAsConnection is using so I can import it into my local machine. However, though I can renew the certificate that Azure Automation uses or upload my own, it doesn't appear that there is an easy way to get the current certificate. I know this is by design -- for security -- but for a case like this it's a pain.

I found this article from 2018 that describes how to export the cert while inside a hybrid worker, but the code didn't work for me in Azure Cloud Shell nor locally (Get-AutomationCertificate is undefined): https://www.lunavi.com/blog/how-to-download-an-azure-automation-connection-certificate-locally

Some guides on the web suggest creating a blob storage account and then writing a script to export to it, but that seems like a lot of effort for something I just need once for this repro.

What's the fastest, easiest way to get this certificate for local debugging/repro?


Solution

  • In the end, I used the article from 2018 to craft a quick and dirty way to get the certificate in a consumable format out of the runbook.

    I modified the script that's running in the runbook to add the following lines at the top:

    "*** Exporting Run As Certificate for Debugging"
    $cert = Get-AutomationCertificate -Name "AzureRunAsCertificate"
    $certData = $cert.Export("pfx", 'MySuperSecurePassword')
    
    throw ([Convert]::ToBase64String($certData))
    

    This causes an exception that contains the contents of the certificate as its message. Then when I run this code via the runbook "Test pane", I get the contents of the certificate dumped out in base64 format at the top: The contents of the certificate in Base64-encoded format

    I use an exception just so that: 1) the rest of the runbook does not execute, and 2) I am guaranteed to see the message. I found that if I just did a Write-Host before throwing an exception, the output might not get flushed before the script stopped running.

    I'm then able to copy the base64-encoded part that's in parenthesis, paste it into a file, and decode the contents of the file with [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String in PowerShell or base64 --decode in WSL to get a PFX file. I can then open that PFX file up and import it into my local user store: Settings used for importing the PFX