n8n-nodes-tenable-community
Version:
n8n node for the Tenable One platform
183 lines (182 loc) • 9.29 kB
JavaScript
;
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;