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

Tuesday, April 16, 2024

Powershell Active Directory Permissions Report

 Problem: You need to find out what kinds of access a user or group has in your *GIANT* Active Directory environment. Maybe not so giant, but still.

Cause: Active Directory permissions reports are a pain to build and often get farmed out to third party vendors and you don't want to or can't get said reports to make them pretty.

Resolution: Use my script. What it does: When run in powershell (only tested in 5.1 but should hopefully work in 7.2/7.4), the script finds the AD Forest that the current computer is a part of, gets the domains, scans for objects (of the types you want), and then gets ALL permissions, optionally then filtering them for a user or group. You can even find out what a person *could* do by also including their group membership - this is often a hidden weakness because you can't see anything with the user listed directly. I hope you find this helpful, it took me a while to get right.

https://github.com/hornerit/powershell/blob/master/Get-ActiveDirPermsReport.ps1

Sample input: .\ActiveDirPermsReport.ps1 -UserOrGroup hornerit -ObjectsToScan OUs

Sample output:



Tuesday, March 19, 2024

Azure Automation Hybrid Runbook PSPrivateMetadata missing

Problem: You have a Hybrid Runbook Worker configured with PowerShell 7.2 connected to Azure Automation and a runbook fails to find the Job ID or cannot find the PSPrivateMetadata variable.

Cause: In PowerShell 7.2, it treats the PSPrivateMetadata as an environment variable, so it is in the ENV path.

Resolution: if your 7.2 runbook needs the PSPrivateMetadata, just replace it with $ENV:PSPrivateMetadata. Note that with PS 5.1, you would often get the GUID as $PSPrivateMetadata.JobId.Guid...when you switch to 7.2, it supplies the guid as a string so you only need $ENV:PSPrivateMetadata to get the job id.