UNPKG

n8n-nodes-tenable-community

Version:

n8n node for the Tenable One platform

183 lines (182 loc) 9.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TenableWASClient = void 0; /** * @file Client for interacting with the Tenable Web App Scanning (WAS) API. * Handles authentication and provides methods for all WAS-related operations. */ const n8n_workflow_1 = require("n8n-workflow"); /** * @class TenableWASClient * @description Implements a client for the Tenable Web App Scanning (WAS) API, providing methods * for managing scans, policies, and findings. */ class TenableWASClient { /** * Creates an instance of the TenableWASClient. * @param {ITriggerFunctions | IExecuteFunctions} context The n8n context object for credentials and helpers. */ constructor(context) { this.context = context; } /** * A private helper method to send authenticated requests to the Tenable API. * @private * @param {IHttpRequestOptions} options - The request options. * @returns {Promise<unknown>} A promise that resolves to the API response. * @throws {NodeApiError} Wraps API errors in a standard n8n error. */ async sendRequest(options) { var _a, _b, _c; const credentials = await this.context.getCredentials('tenableOneApi'); const requestOptions = Object.assign(Object.assign({}, options), { headers: Object.assign(Object.assign({}, options.headers), { 'X-ApiKeys': `accessKey=${credentials.accessKey};secretKey=${credentials.secretKey}` }), json: true, url: `https://cloud.tenable.com/${options.url}`, 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 }); } } // ================================================================= // SCANS // ================================================================= /** * Retrieves a list of WAS scans for a given configuration. * @param {object} params The parameters for the request. * @param {string} params.configId The ID of the scan configuration. * @param {IDataObject} [params.qs] Optional query parameters for filtering and pagination. * @returns {Promise<ITenableScan[]>} A promise that resolves to the list of WAS scans. */ async listScans(params) { const response = await this.sendRequest({ method: 'POST', url: `was/v2/configs/${params.configId}/scans/search`, qs: params.qs }); return response.scans; } /** * Creates a new WAS scan for a given configuration. * @param {object} params The parameters for the request. * @param {string} params.configId The ID of the scan configuration. * @param {IDataObject} params.body The request body defining the new scan. * @returns {Promise<ITenableScan>} A promise that resolves to the newly created scan details. */ async createScan(params) { const response = await this.sendRequest({ method: 'POST', url: `was/v2/configs/${params.configId}/scans`, body: params.body }); return response; } /** * Retrieves the details of a specific WAS scan. * @param {object} params The parameters for the request. * @param {string} params.scanId The ID of the scan. * @returns {Promise<ITenableScan>} A promise that resolves to the scan details. */ async getScanDetails(params) { const response = await this.sendRequest({ method: 'GET', url: `was/v2/scans/${params.scanId}` }); return response; } /** * Updates a WAS scan. * @param {object} params The parameters for the request. * @param {string} params.scanId The ID of the scan to update. * @param {IDataObject} params.body The fields to update. * @returns {Promise<unknown>} A promise that resolves to the API response. */ async updateScan(params) { return this.sendRequest({ method: 'PATCH', url: `was/v2/scans/${params.scanId}`, body: params.body }); } /** * Deletes a WAS scan. * @param {object} params The parameters for the request. * @param {string} params.scanId The ID of the scan to delete. * @returns {Promise<unknown>} A promise that resolves to the API response. */ async deleteScan(params) { return this.sendRequest({ method: 'DELETE', url: `was/v2/scans/${params.scanId}` }); } /** * Launches a WAS scan from a configuration. * @param {object} params The parameters for the request. * @param {string} params.configId The ID of the scan configuration to launch. * @returns {Promise<ITenableScan>} A promise that resolves to the launch confirmation details. */ async launchScan(params) { const response = await this.sendRequest({ method: 'POST', url: `was/v2/configs/${params.configId}/scans` }); return response; } // ================================================================= // POLICIES // ================================================================= /** * Retrieves a list of WAS policies (user templates). * @param {object} [options] Optional parameters. * @param {IDataObject} [options.qs] Optional query parameters for filtering and pagination. * @returns {Promise<unknown>} A promise that resolves to the list of WAS policies. */ async listPolicies(options = {}) { return this.sendRequest({ method: 'GET', url: 'was/v2/user-templates/search', qs: options.qs }); } /** * Creates a new WAS policy (user template). * @param {object} options The options for the request. * @param {IDataObject} options.body The policy definition. * @returns {Promise<unknown>} A promise that resolves to the newly created policy details. */ async createPolicy(options) { return this.sendRequest({ method: 'POST', url: 'was/v2/user-templates', body: options.body }); } /** * Retrieves the details of a specific WAS policy. * @param {object} params The parameters for the request. * @param {string} params.policyId The ID of the policy. * @returns {Promise<unknown>} A promise that resolves to the policy details. */ async getPolicyDetails(params) { return this.sendRequest({ method: 'GET', url: `was/v2/user-templates/${params.policyId}` }); } /** * Updates a WAS policy. * @param {object} params The parameters for the request. * @param {string} params.policyId The ID of the policy to update. * @param {IDataObject} params.body The fields to update. * @returns {Promise<unknown>} A promise that resolves to the API response. */ async updatePolicy(params) { return this.sendRequest({ method: 'PUT', url: `was/v2/user-templates/${params.policyId}`, body: params.body }); } /** * Deletes a WAS policy. * @param {object} params The parameters for the request. * @param {string} params.policyId The ID of the policy to delete. * @returns {Promise<unknown>} A promise that resolves to the API response. */ async deletePolicy(params) { return this.sendRequest({ method: 'DELETE', url: `was/v2/user-templates/${params.policyId}` }); } // ================================================================= // FINDINGS // ================================================================= /** * Searches for WAS findings based on specified criteria. * @param {object} [options] Optional parameters. * @param {IDataObject} [options.qs] Optional query parameters for filtering and pagination. * @returns {Promise<ITenableFinding[]>} A promise that resolves to the findings that match the search criteria. */ async searchFindings(options = {}) { const response = await this.sendRequest({ method: 'POST', url: 'was/v2/vulnerabilities/search', qs: options.qs }); return response; } /** * Retrieves the details of a specific WAS finding. * @param {object} params The parameters for the request. * @param {string} params.findingId The ID of the finding. * @returns {Promise<ITenableFinding>} A promise that resolves to the finding details. */ async getFindingDetails(params) { const response = await this.sendRequest({ method: 'GET', url: `was/v2/vulnerabilities/${params.findingId}` }); return response; } } exports.TenableWASClient = TenableWASClient;