Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save davelee212/ad16315a977165c065156c78041eb767 to your computer and use it in GitHub Desktop.

Select an option

Save davelee212/ad16315a977165c065156c78041eb767 to your computer and use it in GitHub Desktop.
lm-get-service-now-info.ps1
function invoke-lmapi {
# Function to interact with the LogicMonitor API.
# DL 14/01/23 - Does not handle paging at the moment so will only return the first 50 results in large resultsets. This hasn't been a problem so far as I've been using
# queries for individual items but something that the function does need to be able to deal with.
param (
[parameter(Mandatory)][string]$company,
[parameter(Mandatory)][string]$accessId,
[parameter(Mandatory)][string]$accessKey,
[parameter(Mandatory)][string]$httpVerb,
[parameter(Mandatory)][string]$resourcePath,
[parameter()][string]$queryString,
[parameter()][string]$body,
[parameter()][string]$downloadTarget
)
<# Use TLS 1.2 #>
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$url = 'https://' + $company + '.logicmonitor.com/santaba/rest' + $resourcePath + $queryString
# Get the current epoch time
$epoch = [Math]::Round((New-TimeSpan -start (Get-Date -Date "1/1/1970") -end (Get-Date).ToUniversalTime()).TotalMilliseconds)
# Encode the access key
$hmac = New-Object System.Security.Cryptography.HMACSHA256
$hmac.Key = [Text.Encoding]::UTF8.GetBytes($accessKey)
# Put everything together into $requestvars to be used as part of the authentication hash
if ($body) {
$requestVars = $httpVerb + $epoch + $body + $resourcePath
} else {
$requestVars = $httpVerb + $epoch + $resourcePath
}
# Create signature for this request using the access key to hash it
$signatureBytes = $hmac.ComputeHash([Text.Encoding]::UTF8.GetBytes($requestVars))
$signatureHex = [System.BitConverter]::ToString($signatureBytes) -replace '-'
$signature = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($signatureHex.ToLower()))
# Create dictionary to contain headers
$auth = 'LMv1 ' + $accessId + ':' + $signature + ':' + $epoch
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization",$auth)
$headers.Add("X-Version",'3')
$headers.Add("Content-Type",'application/json')
# Make the request to the API (downloading a file or adding $body if it was passed)
# If the request fails with a 429 "Too Many Requests" error code, then we're likely hammering the API too hard, so we wait 10 seconds and retry
Do {
$errorCode = 0
try {
if ($downloadTarget) {
$response = Invoke-RestMethod -Uri $url -Method $httpVerb -Header $headers -OutFile $downloadTarget -TimeoutSec 300 -StatusCodeVariable statuscode
} elseif ($body) {
$response = Invoke-RestMethod -Uri $url -Method $httpVerb -Header $headers -Body $body -TimeoutSec 30 -StatusCodeVariable statuscode
} else {
$response = Invoke-RestMethod -Uri $url -Method $httpVerb -Header $headers -TimeoutSec 30 -StatusCodeVariable statuscode
}
} catch {
Write-Host "Error: $_"
[int]$errorCode = $_.exception.response.statusCode
# Write-Host "Error code: $errorCode"
}
if ($errorCode -eq 429) {
Write-Host "429 Too Many Requests - Waiting 10 seconds and retrying..."
Start-Sleep -Seconds 10
}
} while ($errorCode -eq 429)
# Return the response from the API
return $response
}
$company = "your-account-name" # Replace with your LogicMonitor company name
$accessId = "your-access-id" # Replace with your LogicMonitor access ID
$accessKey = "your-access-key" # Replace with your LogicMonitor access key
$daysAgo = 2 # Number of days to look back for alerts
# calculates the epoch time for the start of the query
$startEpoch = (Get-Date (Get-Date).AddDays(-$daysAgo) -UFormat %s)
# query string includes the ##EXTERNALTICKETID# custom column and filters for alerts created after the startEpoch. Will get the first 1000 results, you'll need to put a loop in to handle paging if you expect more than that.
$queryString = ('?customColumns=%23%23EXTERNALTICKETID%23%23&size=1000&offset=0&filter=startEpoch>:' + $startEpoch)
# call the LogicMonitor API to get the alerts
$alerts = (invoke-lmapi `
-company $company `
-accessId $accessId `
-accessKey $accessKey `
-httpVerb "GET" `
-resourcePath "/alert/alerts" `
-queryString $queryString).items
# Filter the alerts to only include those that went to a rule where the name includes "Service Now" and that were not suppressed (e.g. not SDT at the time)
# Does a bit of manipulation to extract the ServiceNow Incident ID from the custom column ##EXTERNALTICKETID##
$alerts | where-object {$_.rule -like "*Service Now*" -And !($_.suppressor)} | Select-Object `
@{Name="Alert ID";Expression={$_.id}}, `
@{Name="InternalId";Expression={$_.InternalId}}, `
@{Name="External_Ticket_ID_RAW";Expression={$_.customColumns.'##EXTERNALTICKETID##'}}, `
@{Name="SNOWIncidentId";Expression={$_.customColumns.'##EXTERNALTICKETID##'.split(':')[1].trim()}}, `
@{Name="SNOWLinks";Expression={$_.alertExternalTicketUrl.'servicenowIncidentLinks'}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment