LogicMonitor + Catchpoint: Enter the New Era of Autonomous IT

Learn more

LogicMonitor’s Rubrik Security Cloud Monitoring package leverages the Rubrik Security Cloud GraphQL API to monitor the health, capacity, and performance of Rubrik-managed clusters. 

This monitoring package provides the following monitoring capabilities:

  • Cluster Performance Metrics—Monitor total capacity, including used, available, snapshot, and capacity utilization percentages. 
  • Compression Statistics—Track pre- and post-compression data volumes to understand storage efficiency and compression ratios. 
  • Cluster Health—Monitor cluster status, version information, and node and disk counts. 
  • Webhook Integration—Use Rubrik Security Cloud webhook notifications to send real-time alerts and events directly to LM Logs.

The monitoring package uses GraphQL queries in Rubrik Security Cloud, eliminating the need for direct access to individual Rubrik nodes while providing centralized visibility across all clusters in your environment.

For more information about Rubrik Security Cloud, see Rubrik Security Cloud API from Rubrick.

Requirements for Rubrik Security Cloud Monitoring

To use the Rubrik Security Cloud Monitoring package, you need the following:

  • A Rubrik Security Cloud account and portal access
  • A Rubrik Client ID and secret key credentials and appropriate permissions to query cluster information through GraphQL API 
    For more information, see Authentication from Rubrik. 
  • Clusters registered in your Rubrik Security Cloud
  • Collector outbound HTTPS access to https://[portal-name].my.rubrik.com

To configure the webhook integration for Rubrik Security Cloud, you need a bearer token created in LogicMonitor. For more information, see Adding a Bearer Token

Adding Rubrik Security Cloud Resources into Monitoring

Rubrik Security Cloud resources can be onboarded into monitoring using one of the following methods:

  • Enhanced Script NetScan (recommended)
  • Manually adding resources

For more information on NetScans, see NetScan Overview.

Using the Enhanced Script NetScan to Add Resources

  1. In LogicMonitor, navigate to Modules > Exchange.
  2. Locate and install the Rubrik Security Cloud module package.
  3. Navigate to Resources > Add Advanced NetScan
  4. Enter a name for the NetScan (for example, Rubrik Security Cloud Clusters). 
  5. Select the Collector to run the NetScan. 
  6. Select “Enhanced Script NetScan” from the Method dropdown menu. 
  7. In the Enhanced Script section, select Device Credentials > Use custom credentials for this scan. 
  8. Add the following properties to provide the NetScan with the required Rubrik Security Cloud credentials and to control how resources are organized:
PropertyDescriptionRequired
rubrik.rsc.portalRubrik Security Cloud portal nameYes
rubrik.rsc.clientidService account client IDYes
rubrik.rsc.keyService account secret keyYes
custom.folder.nameRoot device group for discovered clustersNo
lmaccess.id  or logicmonitor.access.idLM API access ID for device deduplicationYes
Note: Required unless skip.device.dedupe is set to true.
lmaccess.key or logicmonitor.access.keyLM API access key for device deduplicationYes
Note: Required unless skip.device.dedupe is set to true
hostname.sourceControls hostname collision handlingNo
skip.device.dedupeSkip device deduplication checksNo
lmapi.timelimit.secTime limit for LM API lookupsNo
  1. Select Embed a Groovy script and embed the following script:

Warning: Do not edit the script. Edited Enhanced Script NetScans are not supported. If the LogicMonitor-provided script is edited, LogicMonitor Support can require you to overwrite your edits with the supported script if problems arise. The Enhanced Script NetScan limits LM Envision Resource creation to <= 600 per hour. To create more than 600 Resources, schedule the NetScan to recur each hour until all resources are added. 9. In the Schedule section, select Run this NetScan on a schedule. For dynamic environments, you can schedule the NetScan to run as frequently as hourly.

/*******************************************************************************
 * © 2007-2026 - LogicMonitor, Inc. All rights reserved.
 ******************************************************************************/

import com.santaba.agent.groovy.utils.GroovyScriptHelper as GSH
import com.logicmonitor.mod.Snippets
import groovy.json.JsonOutput

// To run in debug mode, set to true
Boolean debug = false

// Set props object based on whether or not we are running inside a netscan or debug console
def props
try {
    hostProps.get("system.hostname")
    props = hostProps
    debug = true  // set debug to true so that we can ensure we do not print sensitive properties
}
catch (MissingPropertyException) {
    props = netscanProps
}

// Import any needed credentials or properties that have been set in the UI
// Required properties
def rscPortal = props.get('rubrik.rsc.portal')
def rscClientId = props.get('rubrik.rsc.clientid')
def rscSecret = props.get('rubrik.rsc.key')

// Optional properties
def rootFolder = props.get('custom.folder.name', 'Rubrik Security Cloud')
Boolean skipDeviceDedupe = props.get("skip.device.dedupe", "false").toBoolean()
String hostnameSource    = props.get("hostname.source", "")?.toLowerCase()?.trim()


// Bail out early if we don't have the necessary credentials
if (!rscPortal || !rscClientId || !rscSecret) {
    throw new Exception(" Must provide Rubrik Security Cloud credentials (rubrik.rsc.portal, rubrik.rsc.clientid, rubrik.rsc.key) to run this script.")
}

def modLoader = GSH.getInstance(GroovySystem.version).getScript("Snippets", Snippets.getLoader()).withBinding(getBinding())
def lmEmit = modLoader.load("lm.emit", "1.1")
def lmDebug   = modLoader.load("lm.debug", "1.0").debugSnippetFactory(out, debug)
def http = modLoader.load("proto.http", "0").httpSnippetFactory(props)

// Only initialize lmApi snippet class if customer has not opted out
def lmApi
if (!skipDeviceDedupe) {
    def lmApiSnippet = modLoader.load("lm.api", "0")
    lmApi = lmApiSnippet.lmApiSnippetFactory(props, http, lmDebug)
}

// Initialize Rubrik Security Cloud snippet
def collectorCache = modLoader.load("lm.cache", "0")
def rubrikSC = modLoader.load("rubrik.securitycloud", "0").create(props, lmDebug, http, collectorCache)

// Get information about devices that already exist in LM portal
List fields = ["name", "currentCollectorId", "displayName"]
Map args = ["size": 1000, "fields": fields.join(",")]
def lmDevices
// But first determine if the portal size is within a range that allows us to get all devices at once
def pathFlag, portalInfo, timeLimitSec, timeLimitMs
if (!skipDeviceDedupe) {
    portalInfo = lmApi.apiCallInfo("Devices", args)
    timeLimitSec = props.get("lmapi.timelimit.sec", "60").toInteger()
    timeLimitMs = (timeLimitSec) ? Math.min(Math.max(timeLimitSec, 30), 120) * 1000 : 60000 // Allow range 30-120 sec if configured; default to 60 sec

    if (portalInfo.timeEstimateMs > timeLimitMs) {
        lmDebug.LMDebugPrint("Estimate indicates LM API calls would take longer than time limit configured.  Proceeding with individual queries by display name for each device to add.")
        lmDebug.LMDebugPrint("\t${portalInfo}\n\tNOTE:  Time limit is set to ${timeLimitSec} seconds.  Adjust this limit by setting the property lmapi.timelimit.sec.  Max 120 seconds, min 30 seconds.")
        pathFlag = "ind"
    }
    else {
        lmDebug.LMDebugPrint("Response time indicates LM API calls will complete in a reasonable time range.  Proceeding to collect info on all devices to cross reference and prevent duplicate device creation.\n\t${portalInfo}")
        pathFlag = "all"
        lmDevices = lmApi.getPortalDevices(args)
    }
}

// Retrieve all clusters from Rubrik Security Cloud
def allClustersQuery = """
query AllClusters {
  clusterConnection {
    nodes {
      id
      name
      version
      status
      geoLocation {
        address
        latitude
        longitude
      }
      metric {
        totalCapacity
        usedCapacity
      }
    }
  }
}
"""

def allClustersResults = rubrikSC.graphqlQuery(allClustersQuery, [:], "AllClusters")
if (!allClustersResults) {
    throw new Exception("Failed to retrieve clusters from Rubrik Security Cloud.")
}

// Extract clusters from the response
def clusters = allClustersResults?.data?.clusterConnection?.nodes
if (!clusters) {
    throw new Exception("No clusters found in Rubrik Security Cloud portal.")
}

lmDebug.LMDebugPrint("Found ${clusters.size()} clusters in Rubrik Security Cloud portal.")

// Build list of resources
List<Map> resources = []

def now = new Date()
def dateFormat = "yyyy-MM-dd'T'HH:mm:ss.s z"
TimeZone tz = TimeZone.getDefault()
Map duplicateResources = [
    "date" : now.format(dateFormat, tz),
    "message" : "Duplicate display names found within LogicMonitor portal wherein hostname in LM does not match hostname in Netscan output.  Refer to documentation for how to resolve name collisions using 'hostname.source' netscan property.",
    "total" : 0,
    "resources" : []
]

// Process each cluster
clusters.each { cluster ->
    String clusterId = cluster.id ?: ""
    String clusterName = cluster.name ?: clusterId
    String hostname = "${clusterId}.rsc.invalid" // Create a fake non-routable hostname since RSC clusters do not have real hostnames
    String displayName = clusterName
    Integer collectorId
    
    // Check for existing device in LM portal with this displayName
    def deviceMatch = false
    if (!skipDeviceDedupe) {
        if (pathFlag == "ind") {
            deviceMatch = lmApi.findPortalDevice(displayName, args)
        }
        else if (pathFlag == "all") {
            deviceMatch = lmApi.checkExistingDevices(displayName, lmDevices)
        }
    }

    if (deviceMatch) {
        // Log duplicates that would cause additional devices to be created
        if (hostname != deviceMatch.name) {
            def collisionInfo = [
                (displayName) : [
                    "Netscan" : [
                        "hostname"    : hostname
                    ],
                    "LM" : [
                        "hostname"    : deviceMatch.name,
                        "collectorId" : deviceMatch.currentCollectorId
                    ],
                    "Resolved" : false
                ]
            ]
    
            // If user specified to use LM hostname on display name match, update hostname variable accordingly
            if (hostnameSource == "lm" || hostnameSource == "logicmonitor") {
                hostname = deviceMatch.name
                collectorId = deviceMatch.currentCollectorId
                deviceMatch = false
                collisionInfo[displayName]["Resolved"] = true
            }
            // If user specified to use netscan data for hostname, update the display name to make it unique
            else if (hostnameSource == "netscan") {
                collisionInfo[displayName]["Resolved"] = true
                displayName = "${displayName} - ${hostname}"
                deviceMatch = false
            }
    
            duplicateResources["resources"].add(collisionInfo)
        }
        // Don't worry about matches where the hostname values are the same
        else {
            deviceMatch = false
        }
    }

    // Build device properties
    Map deviceProps = [
        "rubrik.rsc.clusteruuid": clusterId,
        "rubrik.rsc.portal": rscPortal,
        "rubrik.rsc.clustername": clusterName,
        "rubrik.rsc.clusterversion": cluster.version ?: "",
        "rubrik.rsc.clusterstatus": cluster.status ?: "",
        "rubrik.rsc.clientid": rscClientId ?: "",
        "rubrik.rsc.key": rscSecret ?: ""
    ]
    
    // Add location information if available
    if (cluster.geoLocation?.address) {
        deviceProps["system.location"] = cluster.geoLocation.address
    }
    if (cluster.geoLocation?.latitude != null) {
        deviceProps["system.latitude"] = cluster.geoLocation.latitude
    }
    if (cluster.geoLocation?.longitude != null) {
        deviceProps["system.longitude"] = cluster.geoLocation.longitude
    }

    // Determine group name based on status and location
    List<String> groupName = [rootFolder]
    if (cluster.status == "Connected") {
        if (cluster.geoLocation?.address) {
            groupName.add(cluster.geoLocation.address)
        } else {
            groupName.add("Connected")
        }
    } else {
        groupName.add(cluster.status ?: "Unknown Status")
    }

    Map resource = [
        "hostname"    : hostname,
        "displayname" : displayName,
        "hostProps"   : deviceProps,
        "groupName"   : groupName
    ]

    // Only add the collectorId field to resource map if we found a collector ID above
    if (collectorId) {
        resource["collectorId"] = collectorId
        duplicateResources["resources"][displayName]["Netscan"]["collectorId"] = collectorId
    }

    if (!deviceMatch) {
        resources.add(resource)
        lmDebug.LMDebugPrint("Added cluster: ${clusterName} (${clusterId}) - Status: ${cluster.status}")
    }
}

// Output validated data in JSON format
lmEmit.resource(resources, debug)

// Report devices that already exist in LM via log file named after root folder
if (duplicateResources["resources"].size() > 0) {
    def netscanDupLog = new File("../logs/NetscanDuplicates/${rootFolder.replaceAll(" ", "_")}.json")
    new File(netscanDupLog.getParent()).mkdirs()
    duplicateResources["total"] = duplicateResources["resources"].size()
    def json = JsonOutput.prettyPrint(JsonOutput.toJson(duplicateResources))
    netscanDupLog.write(json)
    if (hostnameSource) {
        lmDebug.LMDebug("${duplicateResources["resources"].size()} devices found that were resolved with hostname.source=${hostnameSource} in netscan output.  See LogicMonitor/Agent/logs/NetscanDuplicates/${rootFolder.replaceAll(" ", "_")}.json for details.")
    }
    else {
        lmDebug.LMDebug("${duplicateResources["resources"].size()} devices found that were not reported in netscan output.  See LogicMonitor/Agent/logs/NetscanDuplicates/${rootFolder.replaceAll(" ", "_")}.json for details.")
    }
}

lmDebug.LMDebugPrint("Successfully discovered ${resources.size()} Rubrik Security Cloud cluster(s)")
return 0
  1. Select Save or Save & Run
    After running the NetScan, review the history for the number of resources added, or for error messages if the NetScan does not create any resources.

Note: By default, clusters discovered by this NetScan are organized using the following group path:

custom.folder.name/cluster name

The default root folder is Rubrik Security Cloud if no custom folder is specified.

Manually Adding Rubrik Security Cloud Resources into Monitoring

  1. In LogicMonitor, create a Rubrik Security Cloud Resource Group.
    For more information, see Adding Resource Groups
  2. Add your Rubrik Security cloud resources into your Rubrik Resource Group. 
  3. Add or verify that the following properties are set on the resources or in your resources group:
PropertyValueRequired
rubrik.rsc.portalThe name of your Rubrik Security Cloud portal (for example, mycompany for mycompany.my.rubrik.com).Yes
rubrik.rsc.clientidThe Service Account Client ID for authenticating Rubrik Security Cloud.Yes
rubrik.rsc.keyThe Service Account Secret for authenticating Rubrik Security Cloud.Yes
rubrik.rsc.clusteruuidThe unique identifier (UUID) for the specific cluster. Set automatically by NetScan and must be manually assigned for manually added resources.Yes
system.categoriesAdd rubrik_securitycloud to enable device reconciliation and categorization (automatically set by the PropertySource).Yes

Note: Service account credentials may be set at a parent group level to apply automatically to all Rubrik Security Cloud cluster resources.

For more information on setting properties, see Resource and Instance Properties.

Configuring Webhook Integration for On-Premises Rubrik Node Monitoring

  1. In Rubrik Security Cloud, configure the webhook.
    For more information, see Events from Rubrik.
    The following values are required:
FieldValue
Webhook Endpointhttps://<your-portal>.logicmonitor.com/rest/logging/ingest/webhook
Bearer TokenEnter in the bearer Token you created in LogicMonitor
  1. Test the webhook configuration to ensure alerts are flowing properly. 
    For more information, see Events from Rubrik.

Import LogicModules

Import all Rubrik Security Cloud LogicModules from LM Exchange.

If modules already exist, ensure they the lastest version. After import, discovery and data collection begin automatically.

Troubleshooting

Use the following guidance to help diagnose and resolve common issues when deploying or operating the Rubrik Security Cloud Monitoring package:

IssueResolution
Authentication FailuresVerify service account credentials and portal name configuration.
No Data CollectedVerify required properties, cluster UUID, and collector HTTPS connectivity.
Webhook IssuesConfirm webhook configuration and bearer token permissions.
API Rate LimitingReduce polling frequency or review collection intervals.

LogicModules in Package

LogicMonitor’s package for Rubrik Security Cloud Monitoring consists of the following LogicModules. For full coverage, ensure all of the following LogicModules are imported into your LogicMonitor platform:

Display NameTypeDescription
addCategory_RubrikSecurityCloudPropertySourceAssigns required categories and properties to Rubrik Security Cloud cluster resources.
Rubrik_SecurityCloud_GlobalPerformanceDataSourceMonitors cluster health, capacity, and inventory metrics.
Rubrik_SecurityCloud_CompressionStatisticsDataSourceMonitors cluster compression statistics.
Rubrik_SecurityCloud_WebhooksLogSourceReceives webhook alerts and logs from Rubrik Security Cloud.

When setting static datapoint thresholds on the various metrics tracked by this package’s DataSources, LogicMonitor follows the technology owner’s best practice KPI recommendations.

Recommendation: If necessary, adjust these predefined thresholds to meet the unique needs of your environment. For more information on tuning datapoint thresholds, see Static Thresholds for Datapoints.

14-day access to the full LogicMonitor platform