Tuesday, June 11, 2024

Connect to Azure using Connect-AzAccount and a KeyVault or Automation Vault

Situation: You want to connect to Azure using a certificate file (typically a PFX file) in a PowerShell script, especially in an unattended scenario or a multi-tenant environment.

Problem: Connect-AzAccount doesn't yet allow the use of x509 certificate objects, only a CertificatePath that you must specify to a local store OR a CertificateThumbprint that indicates that you installed the certificate on the local computer.

Resolution: You can use PowerShell commands to perform the following steps to make it work -

  1. Get the Certificate file and a credential of some sort (usually a service principal involved in the process anyway)
  2. Export the password-encoded certificate PFX file to a temp folder on the local machine
  3. Connect to AzAccounts using the temp path and the password.
You can view my commands below as they aren't a full script and thus not in my github. My scenario is to use Azure Automation's Certificates and its Credentials section to store a service principal account password securely, the Cert securely, and leverage the Credential password to secure the file, disconnect from the automatic Automation Az connection, and connect with the certificate. This is all done within a Runbook. If you needed to do this from a KeyVault, then you would need to obtain the Certificate from the Vault and include the private key in the particular x509 object you retrieve:

$Credential = Get-AutomationPSCredential -Name "MyServicePrincipal"
$Tenant = "YOURTENANTGUIDGOESHERE"
$ApplicationId = "YOURAPPLICATIONIDGOESHERE"

#Prep azure connection by getting cert, exporting to local temp file securely, then using for Az connection
$Cert = Get-AutomationCertificate -Name 'MyAppCertificate'
$CertTempPath = "$env:TEMP\temp.pfx" #You can name it dynamically if you like

try {
    $PfxCert = $Cert.Export(3,$($Credential.GetNetworkCredential().Password))
} catch {
    $Msg = "Error exporting cert - $_"
    Write-Error -Message $Msg
    Disconnect-AzAccount *> $null
    throw $Msg
}
if (Test-Path $CertTempPath) {
    Remove-Item -Path $CertTempPath
}
try {
Set-Content -Value $PfxCert -Path $CertTempPath -Encoding Byte #<-- PS 5.1
    #Set-Content -Value $pfxCert -Path $certTempPath -AsByteStream #<-- PS 6+
} catch {
    $Msg = "Error setting content - $_"
    Write-Error -Message $Msg
    Disconnect-AzAccount *> $null
    throw $Msg
}
try {
    $CertArgs = @{
        CertificatePath = $certTempPath
        CertificatePassword = $Credential.Password
        Tenant = $Tenant
        ApplicationId = $ApplicationId
    }
} catch {
    Write-Error -Message "Unable to get Automation Cert info - $($_.exception.message)";
    Disconnect-AzAccount *> $null
    throw
}
try {
    Disconnect-AzAccount *> Out-Null
    Write-Output -InputObject "Disconnected from Az. Connecting using $($Credential.UserName)..."
    $context = Connect-AzAccount @CertArgs -ErrorAction Stop
    Write-Output -InputObject "Done"
} catch {
    Disconnect-AzAccount *> Out-Null
    throw "Unable to connect to AzAccount using supplied Credential"
} #DO STUFF HERE LIKE GET-AZADUSER OR SOMETHING Disconnect-AzAccount *> Out-Null #Always close out your sessions properly Remove-Item -Path $CertTempPath #Remove the PFX file so it is unobtainable

No comments:

Post a Comment