Home > Software design >  Custom Azure Log from Azure Resource Graph query
Custom Azure Log from Azure Resource Graph query

Time:01-30

I have Runbook under Azure automation account that should collect results from Resource graph query and pass it to Log analytics as custom log. I have managed to create a script that works fine.

$customerId = "xxxxxxxxx"
$SharedKey = "xxxxxxxxxxxxxxxx"
$LogType = "MyRecord"
$TimeStampField = ""
#function block
Function Connect-ToAzure {
    $connectionName = "AzureRunAsConnection" 
    $automationAccountName = Get-AutomationVariable -Name 'automationAccountName' 
    Write-Output "Azure Automation Account Name - $automationAccountName"
    $connectionName = "AzureRunAsConnection"
    Write-Output "Connection Name - $connectionName"
    $servicePrincipalConnection = Get-AutomationConnection -Name $connectionName 
    Write-Output "Logging in to Azure..."
    Connect-AzAccount -ServicePrincipal -Tenant $servicePrincipalConnection.TenantId `
        -ApplicationId $servicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint `
        -Subscription $servicePrincipalConnection.SubscriptionId   
}
Function Build-Signature ($customerId, $sharedKey, $date, $contentLength, $method, $contentType, $resource)
{
    $xHeaders = "x-ms-date:"   $date
    $stringToHash = $method   "`n"   $contentLength   "`n"   $contentType   "`n"   $xHeaders   "`n"   $resource

    $bytesToHash = [Text.Encoding]::UTF8.GetBytes($stringToHash)
    $keyBytes = [Convert]::FromBase64String($sharedKey)

    $sha256 = New-Object System.Security.Cryptography.HMACSHA256
    $sha256.Key = $keyBytes
    $calculatedHash = $sha256.ComputeHash($bytesToHash)
    $encodedHash = [Convert]::ToBase64String($calculatedHash)
    $authorization = 'SharedKey {0}:{1}' -f $customerId,$encodedHash
    return $authorization
}

# Create the function to create and post the request
Function Post-LogAnalyticsData($customerId, $sharedKey, $body, $LogType)
{
    $method = "POST"
    $contentType = "application/json"
    $resource = "/api/logs"
    $rfc1123date = [DateTime]::UtcNow.ToString("r")
    $contentLength = $body.Length
    $signature = Build-Signature `
        -customerId $customerId `
        -sharedKey $sharedKey `
        -date $rfc1123date `
        -contentLength $contentLength `
        -method $method `
        -contentType $contentType `
        -resource $resource
    $uri = "https://"   $customerId   ".ods.opinsights.azure.com"   $resource   "?api-version=2016-04-01"

    $headers = @{
        "Authorization" = $signature;
        "Log-Type" = $LogType;
        "x-ms-date" = $rfc1123date;
        "time-generated-field" = $TimeStampField;
    }
    Write-Output "Sending a request"
    $response = Invoke-WebRequest -Uri $uri -Method $method -ContentType $contentType -Headers $headers -Body $body -UseBasicParsing
    return $response.StatusCode
    Write-Output "Request has been sent"
}
try {
    Write-Output "Starting runbook"
    $customerId = "xxxxxxxxx"
    $SharedKey = "xxxxxxxxxxxxxxxx"
    $LogType = "MyRecord"
    $Query = @'
        resources
        | where type == "microsoft.compute/disks"
        | extend diskState = properties.diskState
        | extend diskSizeGB = properties.diskSizeGB
        | where properties['encryptionSettingsCollection'] != "enabled"
        | where diskState == "Attached" or diskState == "Reserved"
        | extend diskCreationTime = properties.timeCreated
        | extend hostVM = split(managedBy,"/")[-1]
        | project diskCreationTime, name, resourceGroup, hostVM, diskState
'@
Connect-ToAzure
        $Result = (Search-AzGraph -Query $Query -First 1000)
        $jsonResult = $Result | ConvertTo-Json
     
Post-LogAnalyticsData -customerId $customerId -sharedKey $sharedKey -body $jsonResult -logType $LogType
    Write-Output "Runbook has been finished"
}
catch {
    Write-Error -Message $_
    break  
}

However, I have an issue with collection of logs. I gather logs only from one subscription.

Can someone please help with code adjustment? How can I gather results from all subscriptions not just from one? I assume it should be foreach ($sub in $subs), but not sure how to do it combined with this graph query.

CodePudding user response:

As the run as account will retire by Sep'23 so I would recommend using managed identities approach in your runbook i.e., configure role assignment for managed identity across multiple subscriptions as explained here and update your Connect-ToAzure function block something like shown below. For more context with regards to it, refer this Azure document.

$automationAccountName = Get-AutomationVariable -Name 'automationAccountName' 
Write-Output "Azure Automation Account Name - $automationAccountName"
Disable-AzContextAutosave -Scope Process | Out-Null
Write-Output "Logging in to Azure..."
$AzureContext = (Connect-AzAccount -Identity).context

Also, you may use UseTenantScope parameter in your Search-AzGraph cmdlet to run the query across all available subscriptions in the current tenant.

  • Related