Rubrik Plugin for Threat Exchange

Rubrik Plugin for Threat Exchange

This document explains how to configure the v1.0.0 Rubrik plugin with the Threat Exchange module of the Cloud Exchange platform. This plugin supports sharing the threat IoCs of type MD5 and SHA256 to the Rubrik’s Threat Hunt page, and can perform a Start Threat Hunt action.

Prerequisites

To complete the plugin configuration, you’ll need:

CE Version Compatibility

Netskope CE: v4.2.0, and v5.0.1

Rubrik Plugin Support

The plugin supports pushing SHA256, and MD5 to Rubrik. The plugin also supports performing the Start Threat Hunt action on the Shared IoCs.

 Fetched indicator types Not Supported
Shared indicator types SHA256, MD5
API Details
List of APIs used
Use Case Method Endpoint API Scope
Get auth token POST /api/client_token None
Get objectFids from Rubrik platform POST /api/graphql Threat Hunt (Read)
Get the clusters present on Rubrik POST /api/graphql Threat Hunt

(Read)

Start Threat Hunt on Rubrik POST /api/graphql Threat Hunt (Read)
Get Auth Token

API Endpoint: /api/client_token

Method: POST

Headers

Key Value
User-Agent netskope-ce-5.0.1-cte-rubrik-v1.0.0

Payload

Parameter Value
client_id <Client ID>
client_secret <Client Secret>

Sample API Response

{
    "access_token": "",
    "expires_in": 43200,
    "Client_id" : “”
}
API for Start Threat Hunt Action
Get ObjectFids from Rubrik

API Endpoint: /api/graphql
Method: POST
Headers

Key Value
User-Agent netskope-ce-5.0.1-cte-rubrik-v1.0.0
Authorization Bearer <Bearer Token>
Content-Type application/json

Payload

GraphQL Query Variables
query SnappableQuery($first: Int, $after: String, $typeFilter: [HierarchyObjectTypeEnum!], $filter: [Filter!], $sortBy: HierarchySortByField, $sortOrder: SortOrder) {
  inventoryRoot {
    descendantConnection(first: $first, after: $after, typeFilter: $typeFilter, filter: $filter, sortBy: $sortBy, sortOrder: $sortOrder) {
      edges {
        cursor
        node {
          id
          ... on WindowsFileset {
            isPassThrough
            __typename
          }
          ... on ShareFileset {
            isPassThrough
            __typename
          }
          ... on LinuxFileset {
            isPassThrough
            __typename
          }
          ... on O365Onedrive {
            userPrincipalName
            __typename
          }
          ...EffectiveSlaColumnFragment
          ...HierarchyObjectClusterColumnFragment
          ...HierarchyObjectLocationColumnFragment
          ...HierarchyObjectNameColumnFragment
          ...HierarchyObjectTypeFragment
          ... on AzureNativeVirtualMachine {
            region
            isAdeEnabled
            resourceGroup {
              subscription {
                name
                __typename
              }
              __typename
            }
            effectiveSlaDomain {
              ...ArchivalSpecFragment
              __typename
            }
            __typename
          }
          ... on AzureNativeManagedDisk {
            region
            isAdeEnabled
            resourceGroup {
              subscription {
                name
                __typename
              }
              __typename
            }
            effectiveSlaDomain {
              ...ArchivalSpecFragment
              __typename
            }
            __typename
          }
          ... on CloudDirectNasExport {
            exportPath
            __typename
          }
          __typename
        }
        __typename
      }
      pageInfo {
        endCursor
        hasNextPage
        hasPreviousPage
        __typename
      }
      __typename
    }
    __typename
  }
}

fragment EffectiveSlaColumnFragment on HierarchyObject {
  id
  effectiveSlaDomain {
    ...EffectiveSlaDomainFragment
    ... on GlobalSlaReply {
      description
      __typename
    }
    __typename
  }
  ... on CdmHierarchyObject {
    pendingSla {
      ...SLADomainFragment
      __typename
    }
    __typename
  }
  __typename
}

fragment EffectiveSlaDomainFragment on SlaDomain {
  id
  name
  ... on GlobalSlaReply {
    isRetentionLockedSla
    retentionLockMode
    __typename
  }
  ... on ClusterSlaDomain {
    fid
    cluster {
      id
      name
      __typename
    }
    isRetentionLockedSla
    retentionLockMode
    __typename
  }
  __typename
}

fragment SLADomainFragment on SlaDomain {
  id
  name
  ... on ClusterSlaDomain {
    fid
    cluster {
      id
      name
      __typename
    }
    __typename
  }
  __typename
}

fragment HierarchyObjectClusterColumnFragment on HierarchyObject {
  ...CdmClusterLabelFragment
  ... on CloudDirectHierarchyObject {
    cluster {
      id
      name
      __typename
    }
    __typename
  }
  __typename
}

fragment CdmClusterLabelFragment on CdmHierarchyObject {
  cluster {
    id
    name
    version
    __typename
  }
  primaryClusterLocation {
    id
    __typename
  }
  __typename
}

fragment HierarchyObjectLocationColumnFragment on HierarchyObject {
  logicalPath {
    name
    objectType
    __typename
  }
  physicalPath {
    name
    objectType
    __typename
  }
  __typename
}

fragment HierarchyObjectNameColumnFragment on HierarchyObject {
  name
  __typename
}

fragment HierarchyObjectTypeFragment on HierarchyObject {
  objectType
  __typename
}

fragment ArchivalSpecFragment on GlobalSlaReply {
  archivalSpec {
    storageSetting {
      targetType
      __typename
    }
    __typename
  }
  archivalSpecs {
    storageSetting {
      targetType
      __typename
    }
    __typename
  }
  __typename
}
{
  "first": 1,
  "filter": [
    {
      "texts": [
        "false"
      ],
      "field": "IS_GHOST"
    },
    {
      "texts": [
        “”
      ],
      "field": "CLUSTER_ID"
    }
  ],
  "sortBy": "NAME",
  "sortOrder": "ASC",
  "typeFilter": [
    "LinuxFileset",
    "ShareFileset",
    "VmwareVirtualMachine",
    "WindowsFileset",
    "HypervVirtualMachine",
    "NutanixVirtualMachine",
    "NAS_FILESET"
  ],
  "after":"Y3Vyc29yOmludDow"
}

Sample API Response

{
    "data": {
        "inventoryRoot": {
            "descendantConnection": {
                "edges": [
                    {
                        "cursor": "Y3Vyc29yOmludDox",
                        "node": {
                            "id": "",
                            "effectiveSlaDomain": {
                                "id": "",
                                "name": "MGMT-12H-30D-1Y-AWS-USW1",
                                "isRetentionLockedSla": false,
                                "retentionLockMode": "NO_MODE",
                                "__typename": "GlobalSlaReply",
                                "description": "Upgraded from Cluster_A"
                            },
                            "pendingSla": null,
                            "__typename": "NasFileset",
                            "cluster": {
                                "id": "",
                                "name": "Cluster_A",
                                "version": "8.1.3-p11-25483",
                                "__typename": "Cluster"
                            },
                            "primaryClusterLocation": {
                                "id": "",
                                "__typename": "DataLocation"
                            },
                            "logicalPath": [
                                {
                                    "name": "/volume1/ISO: **",
                                    "objectType": "FilesetTemplate",
                                    "__typename": "PathNode"
                                },
                                {
                                    "name": "/volume1/ISO",
                                    "objectType": "NasShare",
                                    "__typename": "PathNode"
                                },
                                {
                                    "name": "synology.rubrik.us",
                                    "objectType": "NasSystem",
                                    "__typename": "PathNode"
                                }
                            ],
                            "physicalPath": [
                                {
                                    "name": "/volume1/ISO: **",
                                    "objectType": "FilesetTemplate",
                                    "__typename": "PathNode"
                                },
                                {
                                    "name": "/volume1/ISO",
                                    "objectType": "NasShare",
                                    "__typename": "PathNode"
                                },
                                {
                                    "name": "synology.rubrik.us",
                                    "objectType": "NasSystem",
                                    "__typename": "PathNode"
                                }
                            ],
                            "name": "/volume1/ISO: **",
                            "objectType": "NAS_FILESET"
                        },
                        "__typename": "HierarchyObjectEdge"
                    }
                ],
                "pageInfo": {
                    "endCursor": "Y3Vyc29yOmludDox",
                    "hasNextPage": true,
                    "hasPreviousPage": true,
                    "__typename": "PageInfo"
                },
                "__typename": "HierarchyObjectConnection"
            },
            "__typename": "InventoryRoot"
        }
    }
}
Get Clusters Present on Rubrik

API Endpoint: /api/graphql
Method: POST
Headers

Key Value
User-Agent netskope-ce-5.0.1-cte-rubrik-v1.0.0
Authorization Bearer <Bearer Token>
Content-Type application/json

Payload

GraphQL Query Variables
query ClusterPickerQuery($first: Int, $after: String, $filter: ClusterFilterInput, $sortBy: ClusterSortByEnum, $sortOrder: SortOrder) {
  clusterConnection(filter: $filter, sortBy: $sortBy, sortOrder: $sortOrder, first: $first, after: $after) {
    edges {
      cursor
      node {
        id
        status
        ...ClusterIconNameFragment
        ...ClusterVersionColumnFragment
        ...ClusterTypeColumnFragment
        ...ClusterCapacityColumnFragment
        ...ClusterProtectedCountColumnFragment
        ...ClusterGeoLocationColumnFragment
        ...ClusterNameColumnFragment
        __typename
      }
      __typename
    }
    pageInfo {
      startCursor
      endCursor
      hasNextPage
      hasPreviousPage
      __typename
    }
    __typename
  }
}

fragment ClusterIconNameFragment on Cluster {
  id
  name
  status
  pauseStatus
  state {
    clusterRemovalState
    __typename
  }
  defaultAddress
  passesConnectivityCheck
  connectivityLastUpdated
  ...ClusterNodeConnectionFragment
  globalManagerConnectivityStatus {
    urls {
      url
      isReachable
      __typename
    }
    __typename
  }
  systemStatus
  ccprovisionInfo {
    jobStatus
    jobType
    progress
    vendor
    __typename
  }
  __typename
}

fragment ClusterNodeConnectionFragment on Cluster {
  clusterNodeConnection {
    nodes {
      id
      status
      ipAddress
      __typename
    }
    __typename
  }
  __typename
}

fragment ClusterVersionColumnFragment on Cluster {
  version
  eosDate
  eosStatus
  __typename
}

fragment ClusterTypeColumnFragment on Cluster {
  name
  productType
  type
  clusterNodeConnection {
    nodes {
      id
      __typename
    }
    __typename
  }
  __typename
}

fragment ClusterCapacityColumnFragment on Cluster {
  metric {
    usedCapacity
    availableCapacity
    totalCapacity
    __typename
  }
  __typename
}

fragment ClusterProtectedCountColumnFragment on Cluster {
  productType
  noSqlWorkloadCount
  ...ClusterProtectedSnappablesFragment
  __typename
}

fragment ClusterProtectedSnappablesFragment on Cluster {
  protectedSnappables: snappableConnection(filter: {protectionStatus: Protected}) {
    count
    __typename
  }
  __typename
}

fragment ClusterGeoLocationColumnFragment on Cluster {
  geoLocation {
    address
    __typename
  }
  __typename
}

fragment ClusterNameColumnFragment on Cluster {
  name
  __typename
}
{
  "sortBy": "ClusterName",
  "sortOrder": "ASC",
  "filter": {
    "type": [],
    "name": [
      ""
    ]
  },
  "first": 1
}

Sample API Response

{
    "data": {
        "clusterConnection": {
            "edges": [
                {
                    "cursor": "Y3Vyc29yOmludDow",
                    "node": {
                        "id": "40fdb2a5-3591-40ee-a37a-50bce5240d62",
                        "status": "Connected",
                        "name": "Cluster_A",
                        "pauseStatus": "NOT_PAUSED",
                        "state": {
                            "clusterRemovalState": "REGISTERED",
                            "__typename": "clusterState"
                        },
                        "defaultAddress": "cluster-a-rr.rubrik.us",
                        "passesConnectivityCheck": true,
                        "connectivityLastUpdated": "2024-08-05T10:16:10.000Z",
                        "clusterNodeConnection": {
                            "nodes": [
                                {
                                    "id": "RVMHM223S002373",
                                    "status": "OK",
                                    "ipAddress": "10.8.107.107",
                                    "__typename": "ClusterNode"
                                },
                                {
                                    "id": "RVMHM223S002379",
                                    "status": "OK",
                                    "ipAddress": "10.8.107.106",
                                    "__typename": "ClusterNode"
                                },
                                {
                                    "id": "RVMHM223S002714",
                                    "status": "OK",
                                    "ipAddress": "10.8.107.104",
                                    "__typename": "ClusterNode"
                                },
                                {
                                    "id": "RVMHM223S002718",
                                    "status": "OK",
                                    "ipAddress": "10.8.107.105",
                                    "__typename": "ClusterNode"
                                }
                            ],
                            "__typename": "ClusterNodeConnection"
                        },
                        "__typename": "Cluster",
                        "globalManagerConnectivityStatus": {
                            "urls": [
                                {
                                    "url": "https://rubrik-tme.my.rubrik.com",
                                    "isReachable": true,
                                    "__typename": "GlobalManagerUrl"
                                }
                            ],
                            "__typename": "GlobalManagerConnectivity"
                        },
                        "systemStatus": "OK",
                        "ccprovisionInfo": {
                            "jobStatus": "INITIALIZING",
                            "jobType": "ADD_NODE",
                            "progress": 0,
                            "vendor": "VENDOR_UNKNOWN",
                            "__typename": "CcprovisionInfo"
                        },
                        "version": "8.1.3-p11-25483",
                        "eosDate": "2024-07-25",
                        "eosStatus": "EOS_STATUS_UNSUPPORTED",
                        "productType": "CDM",
                        "type": "OnPrem",
                        "metric": {
                            "usedCapacity": 7113709735936,
                            "availableCapacity": 54306599845888,
                            "totalCapacity": 61420309581824,
                            "__typename": "ClusterMetric"
                        },
                        "noSqlWorkloadCount": 0,
                        "protectedSnappables": {
                            "count": 148,
                            "__typename": "SnappableConnection"
                        },
                        "geoLocation": {
                            "address": "Santa Clara, CA, USA",
                            "__typename": "GeoLocation"
                        }
                    },
                    "__typename": "ClusterEdge"
                }
            ],
            "pageInfo": {
                "startCursor": "Y3Vyc29yOmludDow",
                "endCursor": "Y3Vyc29yOmludDow",
                "hasNextPage": true,
                "hasPreviousPage": false,
                "__typename": "PageInfo"
            },
            "__typename": "ClusterConnection"
        }
    }
}
Start Threat Hunt on Rubrik

API Endpoint: /api/graphql
Method: POST
Headers

Key Value
User-Agent netskope-ce-5.0.1-cte-rubrik-v1.0.0
Authorization Bearer <Bearer Token>
Content-Type application/json

Payload

GraphQL Query Variables
mutation StartThreatHuntMutation($input: StartThreatHuntInput!) 
{   
  startThreatHunt(input: $input)        
       {
          huntId    isSyncSuccessful __typename 
       } 
}
{
    "input": {
    "clusterUuid": "40fdb2a5-3591-40ee-a37a-50bce5240d62",
    "indicatorsOfCompromise": [
      {
        "iocKind": "IOC_HASH",
        "iocValue": "sha256:a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"
      },
      {
        "iocKind": "IOC_HASH",
        "iocValue": "sha256:a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146f"
      }
    ],
    "objectFids": [
      “”
    ],
    "fileScanCriteria": {
      "fileSizeLimits": {
        "maximumSizeInBytes": 1024,
        "minimumSizeInBytes": 5
      },
      "pathFilter": {
        "includes": [
          "*.acm",
          "*.ax",
          "*.cpl",
          "*.dll",
          "*.drv",
          "*.efi",
          "*.exe",
          "*.mui",
          "*.ocx",
          "*.scr",
          "*.sys",
          "*.tsp"
        ],
        "excludes": [],
        "exceptions": []
      }
    },
    "maxMatchesPerSnapshot": 1,
    "name": "Sample threat hunt",
    "shouldTrustFilesystemTimeInfo": true,
    "snapshotScanLimit": {
      "maxSnapshotsPerObject": 1
    }
  }
  }

Sample API Response

{
    "data": {
        "startThreatHunt": {
            "huntId": "892caaf9-90d3-5c87-8297-5862e972a032",
            "isSyncSuccessful": true,
            "__typename": "StartThreatHuntReply"
        }
    }
}
Performance Matrix

Here is the performance reading conducted by sharing 100K indicators to Rubrik on a Large CE Stack with these specifications.

Stack details Size: Large
RAM: 32 GB
CPU: 16 Cores
Indicators fetched from Rubrik NA
Indicators shared with Rubrik ~26K per minute
User Agent

netskope-ce-5.0.1-cte-rubrik-v1.0-0

Workflow

  1. Get your Client ID and Client Secret.
  2. Configure the Rubrik plugin.
  3. Configure a Threat Exchange Business Rule.
  4. Configure Threat Exchange Sharing.
  5. Validate the Rubrik plugin.

Click play to watch a video:

 

Get your Configuration Parameters

Follow the steps in this document to generate the Client ID and Client Secret:

https://docs.rubrik.com/en-us/saas/saas/adding_a_service_account.html?hl=adding%2Cservice%2Caccount

Configure the Rubrik Plugin

  1. Log in to Cloud Exchange and go to Settings > Plugins.
  2. Search for and select the CTE Rubrik plugin box.
  3. Enter the Basic Information:
    • Configuration Name: Plugin configuration name
    • Sync Interval: Interval to fetch data from this plugin source.
    • Aging Criteria: Expire indicators after a specific time.
    • Override Reputation: Set value to override reputation of indicators received from this configuration. Leave empty to keep default.
    • Enable SSL Validation: Enable SSL Certificate validation.
    • Use System Proxy: Use system proxy configured in Settings.

  4. Click Next.
  5. Enter the Configuration Parameters:
    • Base URL: Base URL of Rubrik instance, like https://rubrik01.rubrikdemo.com.
    • Client ID: Client ID generated from the Rubrik platform. To obtain the Client ID, a Service Account JSON needs to be generated. In Rubrik, go to Apps > Settings > Users and Access to generate it.
    • Client Secret: Client Secret generated from the Rubrik platform. To obtain the Client Secret, a Service Account JSON needs to be generated. In Rubrik, go to Apps > Settings > Users and Access to generate it.
  6. Click Save.

Configure a Business Rule for the Rubrik Plugin

A Business Rule is used to filter out the indicators that are to be shared. In order to share IoCs with Rubrik, create a business rule using these steps:

  1. Go to Threat Exchange > Business Rules and click Create New Rule.
  2. Add the Rule name and select the fields through which you want to filter the IoCs. When finished, click Save.

Add Sharing for the Rubrik Plugin

To configure the Sharing, follow these steps:

  1. Go to Threat Exchange > Sharing and click Add Sharing Configuration.
  2. Select a Source configuration (Source from which you want to share data to Rubrik), a Business Rule, and a Destination.
  3. Select the Target value, and enter these values:
    • Threat Hunt Name: Enter the name of the Threat Hunt. A Threat Hunt with this name will be initiated on Rubrik.
    • Cluster Name: Rubrik Cluster for which you want to initiate Threat Hunt.
    • Max File Size to Scan (in KB): Maximum file size in KB to scan. Default is 1024 KB. Maximum supported size is 15000000 KB and minimum supported size is 1 KB.
    • Min File Size to Scan (in KB): Minimum file size in KB to scan. Default is 5 KB. Maximum supported size is 15000000 KB and minimum supported size is 1 KB.
    • Max IOC Matches (Per Snapshot): Maximum IOC matches per snapshot. Default is 1. Maximum supported value is 1000 and minimum supported value is 1.
    • Include Files: Files to include in Threat Hunt.
    • Exclude Files: Files to exclude from Threat Hunt.
    • Do not Exclude Files: File which should not be excluded from Threat Hunt.


  4. Click Save.

Validate the Rubrik Plugin

Pull is not supported.

Validate the Push

Shared IoCs to Rubrik can be verified from logs available on the Logging page of Cloud Exchange.

IoCs shared on Rubrik can be verified at Apps > Data Threat Analytics > Threat Hunt. Click on the Threat Hunt that you created.

Click on the Parameters tab to view the shared IoCs.

Troubleshooting

Unable to configure the Rubrik Plugin

If you are unable to configure the Rubrik Plugin, then it could be due to one of the reasons mentioned-below:

  • Proper permission is not provided to the credentials.
  • Provided incorrect credentials.

To solve the issues mentioned above, follow these steps:

  1. Check the logs of the plugin in Cloud Exchange.
  2. Make sure that provided credentials have proper permissions.
  3. Make sure that correct credentials are provided while configuring the plugin.
Unable to push data to Rubrik

If you are unable to share the IoCs to the Rubrik Plugin, then it could be due to one of these reasons:

  • Invalid value of MD5, and SHA256 provided.
  • If the shared data has type other than MD5, or SHA256.

To solve the issues mentioned above, follow these steps:

  1. Check the logs of the plugin in Cloud Exchange.
  2. Make sure that the MD5, and SHA256 that needs to be shared are valid.
  3. Make sure that the IoCs are of type MD5, or SHA256.
Share this Doc

Rubrik Plugin for Threat Exchange

Or copy link

In this topic ...