vROps – assigned alerts to unknown owners

After upgrading from vROps 7.0 to 7.5 as part of our VCF upgrade to 3.8.0 my users could no longer log in using their AD credentials. A quick Google search later showed that I had to change the AD authentication settings in vROps due to a change. This is a known thing (not really an ‘issue’), resolved in KB article 68131.

Alerts owned by another user

All seemed good for a while, my users could log in, do their thing. A little while later I got some unrelated requests to check out some alerts. Had to change some settings, fiddle with some policies, you know how it works.

Then, I noticed the following:

Who are you people?!

A lot of alerts, both cancelled and active, were owned by users with a long string rather than a username. Strange. Even stranger, I could not release the ownership or take ownership of said alerts. I couldn’t clear them, either. Oh dear. The timeline also lines up with the AD change, so I knew where to look.

Again, a quick Google search and up comes a KB article! Article 2144194 to be exact. That should fix my issue, right?

That’s not a lot to go on…

Admittedly, I haven’t done as much as I should have with RestAPIs. This is a great reason to dive right in and get that sorted. I have used Postman for a little bit, but from what I gather that’s mostly for testing, not really for automation (please let me know if I’m mistaken). I do have quite a bit of experience with Powershell, so time to put 2 and 2 together.

One of the great things about RestAPI’s is that it’s usually all documented, and documented very well in some cases. The vROps API is one of those cases. Navigate to https://<vrops>/suite-api/docs/rest/index.html to get all the supported calls you can make. Then, head to the API Programming Guide to figure out how to actually use them.

Step 0: authenticate

In order to do anything with the RestAPI, we have to authenticate. From this authentication we get a token we will use for the other API calls.

I’m using a hash table to store my headers which I’ll be using throughout the script. There are two default settings: Content-type and Accept which are both application/json. The Authorization header will contain our token later on.

$table_headers = @{
    "Content-type"  = "application/json"
    "Accept"        = "application/json"
    "Authorization" = ""
}

The URL to get an authentication token is /api/auth/token/acquire. We need to supply our username and password in the JSON body of the request (don’t use this method when deploying this script. Passwords in Powershell are a big no-no. Use an API call to get them from a central store, or store them in a secure string at least).

$url = "https://<vrops>/suite-api/api/auth/token/acquire"
$json = @"
{
    "username": "<username>",
    "password": "<password>"
}
"@

Then, using the command Invoke-RestMethod we will get a JSON result which we can parse to get our token. This token is prefixed with vRealizeOpsToken and stored in our header table for future use.

$result = Invoke-RestMethod -Uri $url -Method 'Post' -Body $json -Header $table_headers

$table_headers["Authorization"] = "vRealizeOpsToken " + $result.token

Step 1: locate the alert through the Rest client.

Now we have to get the Alert Id. We can use the vROps dashboard to verify if we’re on the right track. Below I have one of the Assigned alerts scoped out to clear.

Using the API documentation we can see the following call: /api/alerts/query. The body of this call can contain multiple parameters, such as alertControlState. Control State is the filter we can apply in the GUI to get assigned or unassigned alerts, so let’s use that.

$url = "https://<vrops>/suite-api/api/alerts/query"
$json = @"
{
    "alertControlState": ["ASSIGNED"]
}
"@

Using this body and url, combined with the headers from the previous example we get our result in JSON format. This is a list of all the alerts currently assigned to a user (regardless if this is a user that exists or not). This is the point where you’d filter if there are some alerts assigned to legit users.

Step 2: collect the UUID of the alert

Using a simple forEach loop we can run through each of those alerts and collect the alertId. We can then store this in a variable, or just straight away pass it to a function, like below named clearAlerts. If we want to do some other things with the alerts, like verify if they belong to a non-user, we’d be using the $alert.alertID object.

$result = Invoke-RestMethod -Uri $url -Method 'Post' -Body $json -Header $table_headers

forEach ($alert in $result.alerts) {
    clearAlerts($alert.alertId)
}

Step 3: clear the alert

The final step is to use the UUID, which we’ve conveniently passed to a function that is called for every alert currently assigned, and release the ownership. The call to do this is:/api/alerts?action=releaseownership. We can then pass the UUID into the JSON body, which will release the stranglehold the non-existent owner has on it.

Function clearAlerts($uuid) {
    $url = "https://<vrops>/suite-api/api/alerts?action=releaseownership"
    $json = @"
    {
        "uuids" : [ "$uuid" ]
    }
"@
    Invoke-RestMethod -Uri $url -Method 'Post' -Body $json -Header $table_headers
}

Refreshing the page in vROps will reveal that the Control State has been set to Open, and the Owner is empty. Of course, this goes for all the previously assigned alerts as well.

No we can finally delete the alert and clear up our environment:

Success!

Overall, a super fun process to get my feet wet with using RestAPIs in PowerShell scripts, and a very successful project to fix an issue. Hope this helps!

Full Powershell script:

$table_headers = @{
    "Content-type"  = "application/json"
    "Accept"        = "application/json"
    "Authorization" = ""
}

Function getToken {
    $url = "https://<vrops>/suite-api/api/auth/token/acquire"
    $json = @"
    {
        "username": "admin",
        "password": "<password>"
    }
"@

    $result = Invoke-RestMethod -Uri $url -Method 'Post' -Body $json -Header $table_headers

    $table_headers["Authorization"] = "vRealizeOpsToken " + $result.token
}

Function getAlerts {
    $url = "https://<vrops>/suite-api/api/alerts/query"
    $json = @"
    {
        "alertControlState": ["ASSIGNED"]
    }
"@

    $result = Invoke-RestMethod -Uri $url -Method 'Post' -Body $json -Header $table_headers

    forEach ($alert in $result.alerts) {
        clearAlerts($alert.alertId)
    }
}

Function clearAlerts($uuid) {
    $url = "https://<vrops>/suite-api/api/alerts?action=releaseownership"
    $json = @"
    {
        "uuids" : [ "$uuid" ]
    }
"@
    Invoke-RestMethod -Uri $url -Method 'Post' -Body $json -Header $table_headers
}