UNPKG

n8n-nodes-tenable-community

Version:

n8n node for the Tenable One platform

108 lines (107 loc) 4.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TenableCSClient = void 0; /** * @file Client for interacting with the Tenable Cloud Security (CS) API. * Handles authentication and provides methods for all CS-related operations, * which are primarily GraphQL-based. */ const n8n_workflow_1 = require("n8n-workflow"); /** * @class TenableCSClient * @description Implements the client for the Tenable Cloud Security (CS) API. * This client is specialized for sending GraphQL queries to the CNS endpoint. */ class TenableCSClient { /** * Creates an instance of the TenableCSClient. * @param {ITriggerFunctions | IExecuteFunctions} context The n8n context object for credentials and helpers. */ constructor(context) { this.context = context; } /** * Sends a GraphQL request to the Tenable Cloud Security API endpoint. * @private * @param {string} query The GraphQL query string. * @param {Record<string, unknown>} variables The variables for the GraphQL query. * @returns {Promise<IDataObject>} A promise that resolves to the API response data. * @throws {NodeApiError} If the API call fails or returns errors in the response body. */ async sendGQLRequest(query, variables) { var _a, _b, _c; const credentials = await this.context.getCredentials('tenableOneApi'); const endpoint = 'https://cloud.tenable.com/cns/graphql'; const headers = { 'X-ApiKeys': `accessKey=${credentials.csApiKey}`, }; const requestOptions = { url: endpoint, method: 'POST', headers, body: { query, variables, }, json: true, timeout: 60000, }; try { return await this.context.helpers.httpRequest(requestOptions); } catch (error) { if (error instanceof n8n_workflow_1.NodeApiError) { const errorDetails = error.cause ? (_a = error.cause.response) === null || _a === void 0 ? void 0 : _a.body : { message: error.message }; const errorMessage = ((_c = (_b = errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.errors) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.message) || (errorDetails === null || errorDetails === void 0 ? void 0 : errorDetails.message) || 'No additional error details provided.'; throw new n8n_workflow_1.NodeApiError(this.context.getNode(), { message: `Tenable API Error: ${errorMessage}` }); } throw new n8n_workflow_1.NodeApiError(this.context.getNode(), { message: error.message }); } } /** * Retrieves a list of all assets from Tenable.cs, automatically handling pagination. * @public * @returns {Promise<ITenableAsset[]>} A promise that resolves to the complete list of assets. */ async listAssets() { const query = ` query listAssets($filter: AssetFilter, $first: Int, $after: String) { assets(filter: $filter, first: $first, after: $after) { nodes { id name type tags ipv4 fqdn netbiosName macAddress operatingSystem source exposure { severity score lastSeen } } pageInfo { hasNextPage endCursor } } } `; const allAssets = []; let hasNextPage = true; let after; while (hasNextPage) { const response = await this.sendGQLRequest(query, { after }); const assets = response.assets; allAssets.push(...assets.nodes); hasNextPage = assets.pageInfo.hasNextPage; after = assets.pageInfo.endCursor; } return allAssets; } } exports.TenableCSClient = TenableCSClient;