Tenable Cloud Security

Tenable Cloud Security is a powerful cloud-native application protection platform (CNAPP) designed to simplify even the most complex cloud security challenges. By combining full asset discovery, deep risk analysis, runtime threat detection, and compliance, it rapidly exposes and closes priority security gaps caused by misconfigurations, risky entitlements, and vulnerabilities. With its unique identity-first approach, Tenable Cloud Security dramatically reduces the cloud attack surface and enforces least privilege at scale, helping organizations minimize risk and strengthen their overall security posture.

Validation Criteria

Your integration with Tenable Cloud Security should meet the following criteria:

  • Ensure that all API calls from your integration use a standard User-Agent string as outlined in the User-Agent Header guide. This enables Tenable to identify your integration's API calls to assist with debugging and troubleshooting.
  • Contact Tenable via the Tech Alliances Email ([email protected]) to validate your third-party integration with Tenable's product or platform.
  • Explain how your integration uses Tenable's API and the specific endpoints utilized. Tenable may request read access to your integration's codebase to validate scalability and recommend best practices.
  • Ensure that your integration uses the proper naming conventions, trademarks, and logos in your integration's user interface. You can download a Media Kit on Tenable's media page.

GraphQL

Tenable Cloud Security uses a GraphQL API, providing flexibility and precise control over the data you retrieve. The API is available via a single endpoint (/graphql) and follows the standard GraphQL schema defined in the official GraphQL documentation. For more information, see the Tenable Cloud Security API documentation.

Best Practices

To build robust and reliable integrations with the Tenable Cloud Security GraphQL API, follow these best practices:

Set a Sensible Polling Interval

  • Limit automated polling to once per day.
  • For user-triggered, on-demand requests, enforce a cooldown period (e.g., 12 hours).

Use Documented and Supported Fields

  • Restrict integrations to documented fields; avoid relying on undocumented fields, which may change without notice.
  • Do not use deprecated fields. Always refer to the documentation for recommended replacements.
  • If Tenable updates field structures or naming conventions, advance notice will be provided. Third parties should update their integrations within 30 days of notification to maintain compatibility.

Query Only Relevant Fields

  • Retrieve only the fields you actually need.
  • Avoid unnecessary fields to maintain efficiency and reduce system overhead.

Prefer Broad Filters

  • Use broader filters instead of highly complex, granular queries.
  • For detailed views, export the full dataset and apply filtering on locally cached data.

Rate Limiting and Quotas

Tenable may enforce rate limits or usage quotas to safeguard system performance, maintain security, and ensure fair usage across all customers.

Use Pagination

GraphQL APIs support cursor-based pagination, which enables you to efficiently retrieve large datasets in smaller chunks. Instead of requesting everything at once, you request a limited number of results and fetch additional pages as needed. For more details, see Pagination in the official GraphQL documentation.

To paginate through results, use the first and after arguments:

  • first: {number} — The number of results to return in the request.
  • after: {cursor} — The cursor pointing to where the next page of results should begin.

Best practices for pagination:

  • Always check pageInfo.hasNextPage to determine if more data is available.
  • Use reasonable page sizes (50–100 results depending on query type) to avoid performance issues.
  • Store and reuse cursors when needed to navigate through result sets.

Example: Fetch First Five Items

The following query retrieves the first five virtual machines with critical or high vulnerabilities:

query {
  VirtualMachines(first: 5, filter: {VulnerabilitySeverities: [Critical, High]}) {
    totalCount
    pageInfo {
      hasNextPage
      endCursor
    }
    edges {
      node {
        Name
        Vulnerabilities {
          Id
          Severity
          Description
        }
        ResolvedVulnerabilities {
          Id
          Severity
          ResolutionTime
        }
      }
    }
  }
}

Example: Paginate Through Findings

Step 1: Initial Query

Start by setting after: null to retrieve the first set of results:

query {
  Findings(first: 10, after: null) {
    nodes {
      Policy {
        Name
      }
      Status
      CreationTime
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Sample Response

{
  "data": {
    "Findings": {
      "nodes": [
        {
          "Policy": {
            "Name": "Inactive IAM role"
          },
          "Status": "Open",
          "CreationTime": "2024-08-13T00:49:10.532Z"
        },
        ...
      ],
      "pageInfo": {
        "hasNextPage": true,
        "endCursor": "cursor10"
      }
    }
  }
}

Since pageInfo.hasNextPage is true, use pageInfo.endCursor (cursor10) to fetch the next page.

Step 2: Fetch the Next Page

Use after: "cursor10" to fetch the next set of results:

query {
  Findings(first: 10, after: "cursor10"){
    nodes {
      Policy {
        Name
      }
      Status
      CreationTime
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Sample Response

{
  "data": {
    "Findings": {
      "nodes": [
        {
          "Policy": {
            "Name": "Virtual Machine has vulnerabilities that should be addressed"
          },
          "Status": "Open",
          "CreationTime": "2024-09-14T00:43:10.578Z"
        },
        ...
      ],
      "pageInfo": {
        "hasNextPage": false,
        "endCursor": "cursor20"
      }
    }
  }
}

When pageInfo.hasNextPage is false, all results have been retrieved. Otherwise, continue paginating using the most recent endCursor.