Datto RMM – Close Alerts Older Than, using PowerShell

The PowerShell script below will connect to Datto RMM’s cloud platform, specifically the Merlot API, and close all non-critical alerts older than a specified date. This is all easily configurable and by simply changing the API endpoints should allow you to connect to any of Datto’s available regions.

For information on enabling or configuring the Datto API please refer to the official documentation – https://rmm.datto.com/help/en/Content/2SETUP/APIv2.htm


The Script

When ran, the script will request your API Key and Secret, you should update the ‘siteGuid’, ‘NewestLogToKeep’ and ‘closeCritical’ variables at the top of the script at minimum. You may also want to search the script for “https://merlot-api.centrastage.net” and update it to your own API endpoint which is dependent on the region your Datto instance is located in.

$APIKey = Read-Host "Please enter the API Key"
$APISecretKey = Read-Host "Please enter the Secret Key"
$siteGuid = "d0c3fffb-4df3-4ff2-9ff7-90435eefffff" # The GUID of the site to query
$NewestLogToKeep = "06/07/2022" # Sets the earliest alerts that will be retained
$requestPerMinuteLimit = 500 # Set the number of requests made per minute
$closeCritical = $false # Set to true to also close critical errors

#region Define Functions 
#requires -Version 3.0
function New-AemApiAccessToken
{
	param
	(
		[string]$apiUrl,
		[string]$apiKey,
		[string]$apiSecretKey
	)

	# Specify security protocols
	[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'

	# Convert password to secure string
	$securePassword = ConvertTo-SecureString -String 'public' -AsPlainText -Force

	# Define parameters for Invoke-WebRequest cmdlet
	$params = @{
		Credential	=	New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ('public-client', $securePassword)
		Uri			=	'{0}/auth/oauth/token' -f $apiUrl
		Method      =	'POST'
		ContentType = 	'application/x-www-form-urlencoded'
		Body        = 	'grant_type=password&username={0}&password={1}' -f $apiKey, $apiSecretKey
	}
	
	# Request access token
	try {(Invoke-WebRequest @params | ConvertFrom-Json).access_token}
	catch {$_.Exception}
}

function New-AemApiRequest
{
	param 
	(
		[string]$apiUrl,
		[string]$apiAccessToken,
		[string]$apiMethod,
		[string]$apiRequest,
		[string]$apiRequestBody
	)

	# Define parameters for Invoke-WebRequest cmdlet
	$params = @{
		Uri         =	'{0}/api{1}' -f $apiUrl, $apiRequest
		Method      =	$apiMethod
		ContentType	= 	'application/json'
		Headers     =	@{
			'Authorization'	=	'Bearer {0}' -f $apiAccessToken
		}
	}

	# Add body to parameters if present
	If ($apiRequestBody) {$params.Add('Body',$apiRequestBody)}

	# Make request
	try {(Invoke-WebRequest @params).Content}
	catch{$_.Exception}
}
#endregion

#region Get all Devices
# Define parameters
$requestDevicesparams = @{
	apiUrl         	=	'https://merlot-api.centrastage.net'
	apiKey         	=	$APIKey
	apiSecretKey   	=	$APISecretKey
	apiMethod      	=	'GET'
	apiRequest		=	'/v2/site/'+$siteGuid+'/devices'
	apiRequestBody	=	''
}

# Request an OAuth token
$apiAccessToken = New-AemApiAccessToken @requestDevicesparams

# Request all device data from the API
$AllDevices = @()
$Result = New-AemApiRequest @requestDevicesparams -ApiAccessToken $apiAccessToken | ConvertFrom-Json
$AllDevices += $Result.devices

# If there is more paginated data then keep requesting until there's not
$NextPage = $Result.pageDetails.nextPageUrl
while($NextPage -ne $null) {
    $newParams = $requestDevicesparams
    $newParams.apiRequest = ($NextPage).Substring($NextPage.IndexOf("/v2"), $NextPage.length - $NextPage.IndexOf("/v2"))
    $Result = New-AemApiRequest @requestDevicesparams -ApiAccessToken $apiAccessToken | ConvertFrom-Json

    $NextPage = $Result.pageDetails.nextPageUrl
    $AllDevices += $Result.devices
}
#endregion

$AllAlerts = @()
$currentIndex = 1
foreach($device in $AllDevices) {
    #region Get alerts for each device

    # Show a nice progress bar
    Write-Progress -Id 0 -Activity "Retrieving alerts for all devices" -Status "$currentIndex of $($AllDevices.Count)" -PercentComplete (($currentIndex / $AllDevices.Count) * 100)

    $DeviceID = $device.uid

    $requestDevicesparams = @{
	    apiUrl         	=	"https://merlot-api.centrastage.net"
	    apiKey         	=	$APIKey
	    apiSecretKey   	=	$APISecretKey
	    apiMethod      	=	'GET'
	    apiRequest		=	"/v2/device/$($DeviceID)/alerts/open"
	    apiRequestBody	=	''
    }

    $OpenAlerts = @()
    $Request = New-AemApiRequest @requestDevicesparams -ApiAccessToken $apiAccessToken | ConvertFrom-Json
    $OpenAlerts += $Request.alerts

    $NextPage = $Request.pageDetails.nextPageUrl
    while($NextPage -ne $null) {
        $newParams = $requestDevicesparams
        $newParams.apiRequest = ($NextPage).Substring($NextPage.IndexOf("/v2"), $NextPage.length - $NextPage.IndexOf("/v2"))

        $Request = New-AemApiRequest @requestDevicesparams -ApiAccessToken $apiAccessToken | ConvertFrom-Json
        $OpenAlerts += $Request.alerts

        $NextPage = $Request.pageDetails.nextPageUrl
    }
    
    $AllAlerts += $OpenAlerts

    Write-Host -ForegroundColor Green "Found $($OpenAlerts.count) open alerts for $($Device.hostname)"
    $currentIndex++
    #endregion
}



#region Close all alerts that are not critical priority

# Set the current index to 1 (Used for a progress bar)
$currentIndex = 1
$cutoffUnixTimestamp = (New-TimeSpan -Start (Get-Date "01/01/1970") -End (Get-Date -Date $NewestLogToKeep)).TotalMilliseconds # Calculate the cutoff Unix time based on NewestLogToKeep

$pause = 1000/($requestPerMinuteLimit/60) # Calculate the pause between requests

foreach ($alert in $AllAlerts) {
    # Show a nice progress bar
    Write-Progress -Id 0 -Activity "Closing alerts" -Status "$currentIndex of $($AllAlerts.Count)" -PercentComplete (($currentIndex / $AllAlerts.Count) * 100)

    # Filter out any alerts that are critical or that are newer than the cutoff date
    if($alert.priority -eq 'Critical' -and !($closeCritical)) {
        Write-host -ForegroundColor yellow "Excluded critical alert for $($alert.alertSourceInfo.deviceName)"
    } elseif($alert.timestamp -gt $cutoffUnixTimestamp) {
        Write-host -ForegroundColor yellow "Excluded alert for $($alert.alertSourceInfo.deviceName) due to timestamp - $($alert.timestamp)"
    } else {
        
        $requestDevicesparams = @{
	        apiUrl         	=	"https://merlot-api.centrastage.net"
	        apiKey         	=	$APIKey
	        apiSecretKey   	=	$APISecretKey
	        apiMethod      	=	'POST'
	        apiRequest		=	"/v2/alert/$($alert.alertUid)/resolve"
	        apiRequestBody	=	''
        }

         New-AemApiRequest @requestDevicesparams -ApiAccessToken $apiAccessToken
    }
    
    $currentIndex++
    Start-Sleep -Milliseconds $pause
}

#endregion

Try Cartel Empire today. A completely free, persistent-MMO developed by me.
Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.