Sorting bits into bytes...

Trend Micro vRealize Operations Dashboard API

My current customer has been using Trend Micro’s Deep Security Management pack for vRealize Operations Manager. Unfortunately the MP isn’t supported on the latest version of vSphere. And while my customer is bound by government regulation to stay updated, waiting for an update of the MP was not an option. So I was tasked to see if it was possible to collect at least the Trend Micro scan findings/alerts.

As I recently stepped on the API train I was all to keen to try and see what the possibilities are. There is API documentation available, here for example: https://automation.deepsecurity.trendmicro.com/

Here you’ll find Python, Javascript and Java scripts. Not my favorite programming languages. But that’s the beauty of API, it’s not bound to one language. I can use PowerShell as well.

So here are two PowerShell scripts. The first one collects the status and status values of the Trend Micro agents. The second one collects the alerts and the alert definitions from Trend Micro.

DSM Status:

Be sure to update lines 45 until 48 & 78 until 82 according your setup.

<#

Author: Kabir Ali - info@kablog.nl
Scriptname: TMStatus2vROPs
Version: 1.0 (Tested)
Date: May 14 2020 
Why: My customer used a MP for Trend Micro, but that MP is not updated in some time now. While the customer is still in need of Trend micro status and alerts
Remark: Test setup
        vROPs Version 8.1.0 (15972145)
        Trend Micro Deep Security 12

#>


# In order to get the data in vROPs a Linux timestamp is needed.
Function ConvertTo-UnixTimestamp {
    $epoch = Get-Date -Year 1970 -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0	
 	$input | % {		
        $milliSeconds = [math]::truncate($_.ToUniversalTime().Subtract($epoch).TotalMilliSeconds)
        Write-Output $milliSeconds
    }	
}


### Define Defaults ###

# Bypass SSL certificate verification
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
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

### vROPs API Connection ###

# Define vROPs Defaults. User needs API permissions
$vROPsServer = "#############"
$vROPsUser = "#############"
$vROPsPass = "#############"
$vROPsAdapterID = "#############" #Lookup vCenter object in vROPs. The ID can be found in the URL.

#Building vROPS API string & invoking REST API
$vROPsURL = "https://" + $vROPsServer + "/suite-api/api/"
$vROPsAuthURL = "https://" + $vROPsServer + "/suite-api/api/auth/token/acquire"
$Type = "application/json"
# Creating JSON for Auth Body
$AuthJSON =
"{
  ""username"": ""$vROPSUser"",
  ""password"": ""$vROPsPass""
}"
# Authenticating with API
Try 
{
$vROPSSessionResponse = Invoke-RestMethod -Method POST -Uri $vROPsAuthURL -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"}


### DSM API Connection ###

# Define DSM Defaults.
$DSMServer = "#############"
$DSMPort = "#############"
$DSMUserName = "#############"
$DSMPassword = "#############"
$DSMtenant = "#############"

# Build uri and token
$DSM_URI="https://" + $DSMServer + ":" + $DSMport + "/rest/"

$creds = @{
    dsCredentials = @{
        userName = $DSMUserName
        password = $DSMPassword
        }
}

if (!$tenant) {
    $AUTH_URI = $DSM_URI + "authentication/login/primary"
}
else {
    $AUTH_URI = $DSM_URI + "authentication/login"
    $creds.dsCredentials.Add("tenantName", $DSMtenant)
}

$AuthData = ConvertTo-Json -InputObject $creds
$headers = @{'Content-Type'='application/json'}

try{
    $sID = Invoke-RestMethod -Uri $AUTH_URI -Method Post -Body $AuthData -Headers $headers
    Remove-Variable DSMUserName
    Remove-Variable DSMPassword
    Write-Host "[INFO]	Connection to $DSM_URI was SUCCESSFUL"
}
catch{
    Write-Host "[ERROR]	Failed to logon to $DSM_URI.	$_"
    Remove-Variable DSMUserName
    Remove-Variable DSMPassword
    Exit 
}
$sID
$sIDString = "?sID=$sID"


# Generate a cookie session to be used for autherization
$cookie = new-object System.Net.Cookie
$cookie.name = "sID"
$cookie.value =  $sID
$cookie.domain = $DSMServer
$WebSession=new-object Microsoft.PowerShell.Commands.WebRequestSession
$WebSession.cookies.add($cookie)


# Get hosts and status (output is in XML)
$hostsURL = $DSM_URI + "hosts"
$hosts = Invoke-RestMethod -Uri $hostsURL -Method Get -WebSession $WebSession
$hosts.hosts.hosts
$hosts.hosts.hosts.hostStatus

# Build an array to collect the required data
$TMData = $hosts.hosts.hosts
[array]$TMArray = @()
foreach($lines in $TMData){
    $TMArray += New-Object PSObject -Property @{
    TMStatus = ($lines.hostStatus).status
    TMID = $lines.id
    TMName = $lines.displayname
    TMStatusvalue = ($lines.hostStatus).value
    }
}
$TMArray

# Get resources from vROPs
$ResourcesURL = $vROPsURL+"adapters/$vROPsAdapterID/resources"
$vROPsallresources = Invoke-RestMethod -Method GET -Uri $ResourcesURL -Headers $vROPSSessionHeader -ContentType $Type

# Collect only the needed values from the vROPs return data
[array]$vROPsArray = @()
foreach($items in $vROPsallresources.resourceList){
    $vROPsArray += New-Object PSObject -Property @{
    vROPsName = $items.resourceKey.name
    vROPsIdentifier = $items.identifier
    vROPsType = $items.resourceKey.resourceKindKey
    }
}
$vROPsArray

# Combine the required data. For the API call 2 vROPs the vROPs identifier is needed.
[array]$combined = @()
$combined = foreach($obj in $vROPsArray) {
    # Match the names
    $other = $TMArray | Where{$_.TMName -eq $obj.vROPsName}
    # Extra loop for the other data
    foreach ($subObj in @($other)) {
        # Create Array that will have all the data needed to push to vROPs
        $obj | 
        Select vROPsName, vROPsIdentifier, @{Name='TMStatus';Expression={$subObj.TMStatus}}, @{Name='TMStatusvalue';Expression={$subObj.TMStatusvalue}}
    }              
}
$combined

# Lets push the data into vROPs
foreach ($vROPsData in $combined) {
# With all that is required collected, its time to push the data 2 vROPs
$TheTimeIsNow = (Get-Date | ConvertTo-UnixTimestamp)
    # Data is injected into vROPs using a JSON body.
    $jsondata='{
          "property-content" : [ {
            "statKey" : "CustomProperties|Trend Micro Status",
            "timestamps" : [ ' +$TheTimeIsNow+ ' ],
            "values" : [" ' +$vROPsData.TMStatus+ ' "],
            "others" : [ ],
            "otherAttributes" : { }
          }, {
            "statKey" : "CustomProperties|Trend Micro Status Value",
            "timestamps" : [ ' +$TheTimeIsNow+ ' ],
            "values" : [" ' +$vROPsData.TMStatusvalue+ ' "],
            "others" : [ ],
            "otherAttributes" : { }
          } ]
        }'

    Try 
        {
        $TagJSONResponse = Invoke-RestMethod -Method POST -Body $jsondata -Uri ($vROPsURL+'resources/'+$vROPsData.vROPsIdentifier+'/properties') -TimeoutSec 100 -Headers $vROPSSessionHeader -ContentType $Type
        $TagDetailedInfo = $TagJSONResponse.value
        }
        Catch 
        {
        $_.Exception.ToString()
        $error[0] | Format-List -Force
        }
    sleep 0.2 # fix some timeout issues
}
# Close sessions and done
Invoke-RestMethod -Method POST -Uri https://$vROPsServer/suite-api/api/auth/token/release -Headers $vROPSSessionHeader -ContentType $Type
Invoke-RestMethod -Method DELETE ($DSM_URI+'authentication/logout?sID='+$sID)

 

DSM Alerts:

Be sure to update lines 46 until 49 & 79 until 83 according your setup.

<#

Author: Kabir Ali - info@kablog.nl
Scriptname: TMAlerts2vROPs
Version: 1.0 (Tested)
Date: May 14 2020 
Why: My customer used a MP for Trend Micro, but that MP is not updated in some time now. While the customer is still in need of Trend micro status and alerts
Bear in mind that the alerts are added as property values. This is due to the customers requirement to measure response time.
Remark: Test setup
        vROPs Version 8.1.0 (15972145)
        Trend Micro Deep Security 12

#>


# In order to get the data in vROPs a Linux timestamp is needed.
Function ConvertTo-UnixTimestamp {
    $epoch = Get-Date -Year 1970 -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0	
 	$input | % {		
        $milliSeconds = [math]::truncate($_.ToUniversalTime().Subtract($epoch).TotalMilliSeconds)
        Write-Output $milliSeconds
    }	
}


### Define Defaults ###

# Bypass SSL certificate verification
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
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

### vROPs API Connection ###

# Define vROPs Defaults. User needs API permissions
$vROPsServer = "#############"
$vROPsUser = "#############"
$vROPsPass = "#############"
$vROPsAdapterID = "#############" #Lookup vCenter object in vROPs. The ID can be found in the URL.

#Building vROPS API string & invoking REST API
$vROPsURL = "https://" + $vROPsServer + "/suite-api/api/"
$vROPsAuthURL = "https://" + $vROPsServer + "/suite-api/api/auth/token/acquire"
$Type = "application/json"
# Creating JSON for Auth Body
$AuthJSON =
"{
  ""username"": ""$vROPSUser"",
  ""password"": ""$vROPsPass""
}"
# Authenticating with API
Try 
{
$vROPSSessionResponse = Invoke-RestMethod -Method POST -Uri $vROPsAuthURL -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"}


### DSM API Connection ###

# Define DSM Defaults.
$DSMServer = "#############"
$DSMPort = "#############"
$DSMUserName = "#############"
$DSMPassword = "#############"
$DSMtenant = "#############"

# Build uri and token
$DSM_URI="https://" + $DSMServer + ":" + $DSMport + "/rest/"

$creds = @{
    dsCredentials = @{
        userName = $DSMUserName
        password = $DSMPassword
        }
}

if (!$tenant) {
    $AUTH_URI = $DSM_URI + "authentication/login/primary"
}
else {
    $AUTH_URI = $DSM_URI + "authentication/login"
    $creds.dsCredentials.Add("tenantName", $DSMtenant)
}

$AuthData = ConvertTo-Json -InputObject $creds
$headers = @{'Content-Type'='application/json'}

try{
    $sID = Invoke-RestMethod -Uri $AUTH_URI -Method Post -Body $AuthData -Headers $headers
    Remove-Variable DSMUserName
    Remove-Variable DSMPassword
    Write-Host "[INFO]	Connection to $DSM_URI was SUCCESSFUL"
}
catch{
    Write-Host "[ERROR]	Failed to logon to $DSM_URI.	$_"
    Remove-Variable DSMUserName
    Remove-Variable DSMPassword
    Exit 
}
$sID
$sIDString = "?sID=$sID"


# Generate a cookie session to be used for autherization
$cookie = new-object System.Net.Cookie
$cookie.name = "sID"
$cookie.value =  $sID
$cookie.domain = $DSMServer
$WebSession=new-object Microsoft.PowerShell.Commands.WebRequestSession
$WebSession.cookies.add($cookie)




# Collect all the alerts
$AlertsURL = $DSM_URI + "alerts"
$Alerts = Invoke-RestMethod -Uri $AlertsURL -Method Get -WebSession $WebSession
$Alerts.ListAlertsResponse.alerts

# Build an array to collect the required data. One alert can be assigned to multiple objects, the second loop collects all those objects
$Alerttargets = $Alerts.ListAlertsResponse.alerts.targets
[array]$TargetIDs = @()
foreach($item in ($Alerts.ListAlertsResponse.alerts | where {$_.targets})){
    foreach($Targetid in $item.targets){
    $TargetIDs += New-Object PSObject -Property @{
            "TMAlertName" =  $item.name
            "TMAlertDescription" = $item.description -replace "For more information about this and other alerts, visit the Deep Security Help Center at: https://help.deepsecurity.trendmicro.com/"
            "TMTargetID" =  $targetid.urn -replace "urn:tmds:core::0:host/"
            }
    }
}
$TargetIDs

# In order to match the Target IDs to DSM objects, collect all the IDs of all objects in DSM
$hostsURL = $DSM_URI + "hosts"
$TMData = (Invoke-RestMethod -Uri $hostsURL -Method Get -WebSession $WebSession).hosts.hosts
[array]$TMArray = @()
foreach($lines in $TMData){
    $TMArray += New-Object PSObject -Property @{
    TMID = $lines.id
    TMName = $lines.displayname
    }
}
$TMArray

# Match Target IDs and Object IDs together 
[array]$MatchIDs = @()
$MatchIDs = foreach($IDobj in $TargetIDs) {
    # Lookup names
    $OtherData = $TMArray | where {$_.TMID -eq $IDobj.TMTargetID}
    # Extra loop for the other data
    foreach ($subIDObj in @($OtherData)) {
        # Create Array that will have all the data needed to push to vROPs
        $IDobj | 
        Select @{Name='TMName';Expression={$subIDObj.TMName}}, TMAlertName, TMAlertDescription
    }    
}
$MatchIDs

# Get resources from vROPs
$ResourcesURL = $vROPsURL+"adapters/$vROPsAdapterID/resources"
$vROPsallresources = Invoke-RestMethod -Method GET -Uri $ResourcesURL -Headers $vROPSSessionHeader -ContentType $Type

# Collect only the needed values from the vROPs return data
[array]$vROPsArray = @()
foreach($items in $vROPsallresources.resourceList){
    $vROPsArray += New-Object PSObject -Property @{
    vROPsName = $items.resourceKey.name
    vROPsIdentifier = $items.identifier
    }
}
$vROPsArray

# Combine the alerts and vROPsName and vROPsIdentifier
[array]$Alertscombined = @()
$Alertscombined = foreach($obj in $vROPsArray) {
    # Lookup names
    $other = $MatchIDs | Where{$_.TMName -eq $obj.vROPsName}
    # Extra loop for the other data
    foreach ($subObj in @($other)) {
        # Create Array that will have all the data needed to push to vROPs
        $obj | 
        Select vROPsName, vROPsIdentifier, @{Name='TMAlertName';Expression={$subObj.TMAlertName}}, @{Name='TMAlertDescription';Expression={$subObj.TMAlertDescription}}
    }              
}
$Alertscombined

# Lets push the data into vROPs
foreach ($vROPsData in $Alertscombined) {
# With all that is required collected, its time to push the data 2 vROPs
$TheTimeIsNow = (Get-Date | ConvertTo-UnixTimestamp)
    # Data is injected into vROPs using a JSON body.
    $jsondata='{
          "property-content" : [ {
            "statKey" : "CustomProperties|Trend Micro Alert Name",
            "timestamps" : [ ' +$TheTimeIsNow+ ' ],
            "values" : [" ' +$vROPsData.TMAlertName+ ' "],
            "others" : [ ],
            "otherAttributes" : { }
          }, {
            "statKey" : "CustomProperties|Trend Micro Alert Description",
            "timestamps" : [ ' +$TheTimeIsNow+ ' ],
            "values" : [" ' +$vROPsData.TMAlertDescription+ ' "],
            "others" : [ ],
            "otherAttributes" : { }
          } ]
        }'

    Try 
        {
        $TagJSONResponse = Invoke-RestMethod -Method POST -Body $jsondata -Uri ($vROPsURL+'resources/'+$vROPsData.vROPsIdentifier+'/properties') -TimeoutSec 100 -Headers $vROPSSessionHeader -ContentType $Type
        $TagDetailedInfo = $TagJSONResponse.value
        }
        Catch 
        {
        $_.Exception.ToString()
        $error[0] | Format-List -Force
        }
    sleep 0.2 # fix some timeout issues
 }
# Close sessions and done
Invoke-RestMethod -Method POST -Uri https://$vROPsServer/suite-api/api/auth/token/release -Headers $vROPSSessionHeader -ContentType $Type
Invoke-RestMethod -Method DELETE ($DSM_URI+'authentication/logout?sID='+$sID)

 

Collecting the data from Trend Micro is one part of the process. The other part is bundling the collected data into views and thus creating a Trend Micro dashboard.

Here you can download a zip file with everything you need to build the dashboard in vROPs.

Trend Micro DSM vROPs Content

First import the view files.

 

Then import the image. See the txtContent folder for the right name and content. Edit that file with notepad and copy paste the content in step 6.

 

And finally the dashboard.

 

 

The Dashboard looks like this:

 

Enjoy your new dashboard!

Leave a Reply