Since posting an Introduction to PowerShell REST API authentication back in January it has become one of the most popular posts on the blog. It’s helped people consume REST APIs not only on the platforms I reference but port the examples to other REST APIs. Somebody even sent me a screenshot of the post in a reading list for their degree!
Armed with examples of how to authenticate with REST APIs using PowerShell it can still be tricky as most APIs are different. Even between products from the same vendor you’ll see inconsistencies. Each often requires a unique format authentication header, credentials, and token. It can be hard to figure out what is required to get it working, because many vendors give you everything but the 1 thing you need, how to authenticate!
A good example of this is VMware vRealize Operations (vROPs), formerly vCenter Operations Manager. Despite reading my post on authenticating with vCenter 6.5 REST APIs, and searching around the internet, one reader was unable to figure out how to use PowerShell to get a list of alerts from the vROPS 6.7 REST API.
They asked me for help via Drift chat and while I can’t take all requests for examples, as I might not have access the API, a VMware product that I can install in my lab is certainly doable.
So, let’s get down to the PowerShell script itself. How do you authenticate with vROPs and get a list of alerts? It is slightly different to the vCenter 6.5+ REST APIs and I had to use Get-Member quite a few times to figure out where JSON data was being returned.
The examples below are written for PowerShell 5.x. To port to 6.0 remove the certificate exception and add -SkipCertificateCheck on the end of each Invoke-RestMethod. You can download the examples from the zip file below, or continue reading to copy and paste from the post:
First, let’s authenticate and get the token needed for subsequent queries:
################################################ # Configure the variables below for vROPs ################################################ $vROPsServer = "192.168.1.4" # Prompting for credentials, I was only able to login with a local user account in vROPs $vROPsCredentials = Get-Credential -Message "Enter your vROPs credentials" $vROPSUser = $vROPsCredentials.UserName $vROPsCredentials.Password | ConvertFrom-SecureString $vROPsPassword = $vROPsCredentials.GetNetworkCredential().password ################################################ # Nothing to configure below this line ################################################ # Adding certificate exception to prevent API errors ################################################ add-type @" using System.Net; using System.Security.Cryptography.X509Certificates; public class TrustAllCertsPolicy : ICertificatePolicy { public bool CheckValidationResult( ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) { return true; } } "@ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy ################################################ # Building vROPS API string & invoking REST API ################################################ $BaseURL = "https://" + $vROPsServer + "/suite-api/api/" $BaseAuthURL = "https://" + $vROPsServer + "/suite-api/api/auth/token/acquire" $Type = "application/json" # Creating JSON for Auth Body $AuthJSON = "{ ""username"": ""$vROPSUser"", ""password"": ""$vROPsPassword"" }" # Authenticating with API Try { $vROPSSessionResponse = Invoke-RestMethod -Method POST -Uri $BaseAuthURL -Body $AuthJSON -ContentType $Type } Catch { $_.Exception.ToString() $error[0] | Format-List -Force } # Extracting the session ID from the response $vROPSSessionHeader = @{"Authorization"="vRealizeOpsToken "+$vROPSSessionResponse.'auth-token'.token "Accept"="application/json"}
Next, we need to build a list of resources (I.E VMs) with the names mapped to IDs so we can make use of the table when querying alerts:
############################################### # Getting Resources ############################################### $ResourcesURL = $BaseURL+"resources?pageSize=5000" Try { $ResourcesJSON = Invoke-RestMethod -Method GET -Uri $ResourcesURL -Headers $vROPSSessionHeader -ContentType $Type $Resources = $ResourcesJSON.resourcelist } Catch { $_.Exception.ToString() $error[0] | Format-List -Force } # Building table of resources for lookup $ResourceList = @() ForEach($Resource in $Resources) { # Setting values $ResourceHealth = $Resource.resourceHealth $ResourceHealthValue = $Resource.resourceHealthValue $ResourceID = $Resource.identifier $ResourceName = $Resource.resourcekey.name $ResourceType = $Resource.resourcekey.resourceKindKey # Adding to table $ResourceListRow = new-object PSObject $ResourceListRow | Add-Member -MemberType NoteProperty -Name "Name" -Value "$ResourceName" $ResourceListRow | Add-Member -MemberType NoteProperty -Name "Type" -Value "$ResourceType" $ResourceListRow | Add-Member -MemberType NoteProperty -Name "Health" -Value "$ResourceHealth" $ResourceListRow | Add-Member -MemberType NoteProperty -Name "HealthValue" -Value "$ResourceHealthValue" $ResourceListRow | Add-Member -MemberType NoteProperty -Name "ID" -Value "$ResourceID" $ResourceList += $ResourceListRow } $ResourceList | Sort-Object Type,Name | Format-Table
Finally, here is how to get a list of alerts, convert the timestamps from UNIX to a human-readable format, translate the IDs to names, and output the result in a useful table:
############################################### # Getting Current Alerts ############################################### $AlertsURL = $BaseURL+"alerts?pageSize=5000" Try { $AlertsJSON = Invoke-RestMethod -Method GET -Uri $AlertsURL -Headers $vROPSSessionHeader -ContentType $Type $Alerts = $AlertsJSON.alerts } Catch { $_.Exception.ToString() $error[0] | Format-List -Force } $ActiveAlerts = $Alerts | Where-Object {$_.status -eq "Active"} $ActiveAlertsCount = $ActiveAlerts.count # Output of result "ActiveAlerts:$ActiveAlertsCount" ############################################### # Building list of alerts with resource name rather than just ID ############################################### $AlertList = @() ForEach($ActiveAlert in $ActiveAlerts) { # Setting values $AlertName = $ActiveAlert.alertDefinitionId $AlertDescription = $ActiveAlert.alertDefinitionName $AlertResourceID = $ActiveAlert.resourceId $AlertLevel = $ActiveAlert.alertLevel $AlertImpact = $ActiveAlert.alertImpact # Converting date times from Epoch to readable format $AlertStartTimeUTC = $ActiveAlert.startTimeUTC $AlertUpdateTimeUTC = $ActiveAlert.updateTimeUTC $AlertStartTime = [TimeZone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddMilliSeconds($AlertStartTimeUTC)) $AlertUpdateTime = [TimeZone]::CurrentTimeZone.ToLocalTime(([datetime]'1/1/1970').AddMilliSeconds($AlertStartTimeUTC)) # Getting name and type of resource impacted $AlertResourceName = $ResourceList | Where-Object {$_.ID -eq $AlertResourceID} | Select -ExpandProperty Name $AlertResourceType = $ResourceList | Where-Object {$_.ID -eq $AlertResourceID} | Select -ExpandProperty Type # Adding to table $AlertListRow = new-object PSObject $AlertListRow | Add-Member -MemberType NoteProperty -Name "Name" -Value "$AlertResourceName" $AlertListRow | Add-Member -MemberType NoteProperty -Name "Type" -Value "$AlertResourceType" $AlertListRow | Add-Member -MemberType NoteProperty -Name "Level" -Value "$AlertLevel" $AlertListRow | Add-Member -MemberType NoteProperty -Name "Impact" -Value "$AlertImpact" $AlertListRow | Add-Member -MemberType NoteProperty -Name "Alert" -Value "$AlertName" $AlertListRow | Add-Member -MemberType NoteProperty -Name "Description" -Value "$AlertDescription" $AlertListRow | Add-Member -MemberType NoteProperty -Name "Start" -Value "$AlertStartTime" $AlertListRow | Add-Member -MemberType NoteProperty -Name "Update" -Value "$AlertUpdateTime" $AlertList += $AlertListRow } # Output of result $AlertList | Sort-Object Type,Name,Level,Alert | Format-Table # Critical only, you can use this output for other actions such as creating incidents in SNOW! $CriticalAlertList = $AlertList | Where-Object {$_.Level -eq "CRITICAL"} | Sort-Object Name $CriticalAlertList | Format-Table
You can see I have some work to do in my labs:
Now that you’ve programmatically obtained a list of all active alerts in vROPS, what can you do with this data? One fantastic use case that comes to mind is to combine this with my example script on automatically creating incidents in ServiceNow.
By combining both scripts, you can integrate vROPs into SNOW by automatically creating incidents on critical and warning level alerts! With this in place, you’ve potentially made a huge impact on the operational efficiency of your IT team, department, and maybe even the company. I’d certainly be putting that at the top of my CV and highlighting it at my next review!
You can also now browse the vROPs REST API documentation on the following URL to get more data from the APIs:
https://YourvROPsServerHere/suite-api/docs/rest/index.html
If you enjoyed this post please follow me on twitter and happy scripting,