This PowerShell script prints: the site name, the endpoint name, and the hours since last seen for all endpoints that have not been seen in 24 hours or more.
To use it you should substitute your own OAuth2 Client Credentials at the beginning of the file.
Generate client credentials
To generate the credentials, log into OneView and go to Integrate.
For more information on APIs, see OneView API Documentation in the console or hover over the tooltip next to OAuth2 Clients on the Integrate page and click the link.
Find-OfflineEndpoints
# Define client_id and client_secret $client_id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa" $client_secret = "000000ABCDEF000000ABCDEF000000AB000000ABCDEF000000ABCDEF000000AB" # Function to get the token function Get-Token { param ( [string]$client_id, [string]$client_secret ) # Encode client_id and client_secret to base64 $base64EncodedString = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes("${client_id}:${client_secret}")) # Create headers $headers = @{ 'Content-Type' = 'application/x-www-form-urlencoded' 'Authorization' = "Basic $base64EncodedString" } # Create body $body = @{ 'grant_type' = 'client_credentials' 'scope' = 'read' } # Send POST request $response = Invoke-RestMethod -Method Post -Uri 'https://api.malwarebytes.com/oneview/oauth2/token' -Headers $headers -Body $body return $response.access_token } # Function to get sites function Get-Sites { param ( [string]$accessToken ) try { # Create headers $headers = @{ 'Content-Type' = 'application/json' 'Authorization' = "Bearer $accessToken" } # Send GET request $response = Invoke-RestMethod -Method Get -Uri 'https://api.malwarebytes.com/oneview/v1/sites' -Headers $headers return $response } catch { Write-Error "Error occurred: $_" } } function Get-Endpoints { param ( [string]$accessToken, [array]$accountIds, [int]$pageSize, [string]$nextCursor ) try { # Create headers $headers = @{ 'Content-Type' = 'application/json' 'Authorization' = "Bearer $accessToken" } # Create body $body = @{ 'account_ids' = $accountIds 'page_size' = $pageSize 'next_cursor' = $nextCursor } | ConvertTo-Json # Send POST request $response = Invoke-RestMethod -Method Post -Uri 'https://api.malwarebytes.com/api/v2/rmm/endpoints' -Headers $headers -Body $body return $response } catch { Write-Error "Error occurred: $_" } } # Function to find offline endpoints function Find-OfflineEndpoints { try { $accessToken = Get-Token -client_id $client_id -client_secret $client_secret $getSitesResponse = Get-Sites -accessToken $accessToken # Get all of the defined nebula_account_id's $acctIds = $getSitesResponse.sites | Where-Object { $_.nebula_account_id } | ForEach-Object { $_.nebula_account_id } # Call Get-Endpoints with a page_size of 2000 until all pages have been returned $getEndpointsResponse = @{ 'endpoints' = @() } $epNextCursor = '' do { $epRes = Get-Endpoints -accessToken $accessToken -accountIds $acctIds -pageSize 2000 -nextCursor $epNextCursor $epNextCursor = $epRes.next_cursor $getEndpointsResponse.endpoints += $epRes.endpoints } while ($epNextCursor -ne '') # Get all endpoints that haven't been seen in more than 24 hours $now = Get-Date $offlineEndpoints = $getEndpointsResponse.endpoints | Where-Object { -not $_.machine.online } | ForEach-Object { $endpointLastSeen = $null $hoursDifference = $null if ($_.machine.last_seen_at) { try { $endpointLastSeen = [datetime]::Parse($_.machine.last_seen_at) $timeDifference = $now - $endpointLastSeen $hoursDifference = [math]::Truncate($timeDifference.TotalHours) } catch { Continue # skip this entry if there's an error parsing last_seen_at } } else { Continue # skip if no last_seen_at field } [pscustomobject]@{ site = $_.machine.account.name name = $_.display_name hoursSinceLastSeen = $hoursDifference } } | Where-Object { $_.hoursSinceLastSeen -gt 24 } # Print offline endpoints $offlineEndpoints | ForEach-Object { Write-Output "Site name: $($_.site) - Endpoint name: $($_.name) - Hours since last seen: $($_.hoursSinceLastSeen)" } } catch { Write-Error "Error occurred: $_" } } # Call the Find-OfflineEndpoints function Find-OfflineEndpoints