UNPKG

n8n-nodes-binalyze-air

Version:

Binalyze AIR nodes for automating DFIR with n8n workflows

627 lines 25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TasksOperations = void 0; exports.extractTaskId = extractTaskId; exports.extractTaskAssignmentId = extractTaskAssignmentId; exports.isValidTask = isValidTask; exports.isValidTaskAssignment = isValidTaskAssignment; exports.getTasks = getTasks; exports.getTasksOptions = getTasksOptions; exports.executeTasks = executeTasks; const n8n_workflow_1 = require("n8n-workflow"); const helpers_1 = require("../utils/helpers"); const tasks_1 = require("../api/tasks/tasks"); const assignments_1 = require("../api/tasks/assignments/assignments"); const organizations_1 = require("./organizations"); exports.TasksOperations = [ { displayName: 'Operation', name: 'operation', type: 'options', noDataExpression: true, displayOptions: { show: { resource: ['tasks'], }, }, options: [ { name: 'Get', value: 'get', description: 'Retrieve a specific task', action: 'Get a task', }, { name: 'Get Many', value: 'getAll', description: 'Retrieve many tasks', action: 'Get many tasks', }, { name: 'Get Task Assignments', value: 'getTaskAssignments', description: 'Retrieve assignments for a specific task', action: 'Get task assignments', }, { name: 'Wait for Completion', value: 'waitForCompletion', description: 'Wait for a task to complete with polling', action: 'Wait for task completion', }, ], default: 'getAll', }, { displayName: 'Task ID', name: 'taskId', type: 'string', default: '', placeholder: 'Enter task ID', displayOptions: { show: { resource: ['tasks'], operation: ['get', 'getTaskAssignments', 'waitForCompletion'], }, }, required: true, description: 'The ID of the task', }, { displayName: 'Timeout (Seconds)', name: 'timeout', type: 'number', default: 300, placeholder: '300', displayOptions: { show: { resource: ['tasks'], operation: ['waitForCompletion'], }, }, required: true, description: 'Maximum time to wait for completion in seconds. Set to 0 to wait indefinitely.', typeOptions: { minValue: 0, }, }, { displayName: 'Organization', name: 'organizationIds', type: 'resourceLocator', default: { mode: 'id', value: '0' }, placeholder: 'Select organization(s)...', displayOptions: { show: { resource: ['tasks'], operation: ['getAll'], }, }, modes: [ { displayName: 'From List', name: 'list', type: 'list', placeholder: 'Select an organization...', typeOptions: { searchListMethod: 'getOrganizations', searchable: true, }, }, { displayName: 'By ID', name: 'id', type: 'string', validation: [ { type: 'regex', properties: { regex: '^[0-9,\\s]+$', errorMessage: 'Organization IDs must be comma-separated numbers. Use "0" for all organizations.', }, }, ], placeholder: 'Enter organization IDs (comma-separated) or "0" for all', }, { displayName: 'By Name', name: 'name', type: 'string', placeholder: 'Enter organization name', }, ], required: true, description: 'Organization(s) to filter tasks. Use "0" for all organizations, specific IDs for multiple organizations, or search by name for a single organization.', }, { displayName: 'Additional Fields', name: 'additionalFields', type: 'collection', placeholder: 'Add Field', default: {}, displayOptions: { show: { resource: ['tasks'], operation: ['getAll'], }, }, options: [ { displayName: 'Filter By Execution Type', name: 'executionType', type: 'multiOptions', default: [], description: 'Filter tasks by execution type', options: [ { name: 'Now', value: 'now', }, { name: 'Scheduled', value: 'scheduled', }, ], }, { displayName: 'Filter By Name', name: 'name', type: 'string', default: '', description: 'Filter tasks by name (supports partial matches)', }, { displayName: 'Filter By Source', name: 'source', type: 'multiOptions', default: [], description: 'Filter tasks by source', options: [ { name: 'API', value: 'api', }, { name: 'Scheduler', value: 'scheduler', }, { name: 'System', value: 'system', }, { name: 'User', value: 'user', }, { name: 'Webhook', value: 'webhook', }, ], }, { displayName: 'Filter By Status', name: 'status', type: 'multiOptions', default: [], description: 'Filter tasks by status', options: [ { name: 'Assigned', value: 'assigned', }, { name: 'Cancelled', value: 'cancelled', }, { name: 'Completed', value: 'completed', }, { name: 'Failed', value: 'failed', }, { name: 'Processing', value: 'processing', }, { name: 'Scheduled', value: 'scheduled', }, ], }, { displayName: 'Filter By Type', name: 'type', type: 'multiOptions', default: [], description: 'Filter tasks by type', options: [ { name: 'Acquire Image', value: 'acquire-image', }, { name: 'Acquisition', value: 'acquisition', }, { name: 'Agent Deployment', value: 'agent-deployment', }, { name: 'Auto Tagging', value: 'auto-tagging', }, { name: 'Baseline Acquisition', value: 'baseline-acquisition', }, { name: 'Baseline Comparison', value: 'baseline-comparison', }, { name: 'Calculate Hash', value: 'calculate-hash', }, { name: 'Interact Shell', value: 'interact-shell', }, { name: 'Investigation', value: 'investigation', }, { name: 'Isolation', value: 'isolation', }, { name: 'Log Retrieval', value: 'log-retrieval', }, { name: 'Migration', value: 'migration', }, { name: 'Offline Acquisition', value: 'offline-acquisition', }, { name: 'Offline Triage', value: 'offline-triage', }, { name: 'Purge Local Data', value: 'purge-local-data', }, { name: 'Reboot', value: 'reboot', }, { name: 'Retry Upload', value: 'retry-upload', }, { name: 'Shutdown', value: 'shutdown', }, { name: 'Triage', value: 'triage', }, { name: 'Uninstall', value: 'uninstall', }, { name: 'Version Update', value: 'version-update', }, ], }, { displayName: 'Page Number', name: 'pageNumber', type: 'number', default: 1, description: 'Which page of results to return', typeOptions: { minValue: 1, }, }, { displayName: 'Page Size', name: 'pageSize', type: 'number', default: 100, description: 'How many results to return per page', typeOptions: { minValue: 1, }, }, ], }, ]; function extractTaskId(task) { return (0, helpers_1.extractEntityId)(task, 'task'); } function extractTaskAssignmentId(assignment) { return (0, helpers_1.extractEntityId)(assignment, 'assignment'); } function isValidTask(task) { return (0, helpers_1.isValidEntity)(task, ['name']); } function isValidTaskAssignment(assignment) { return (0, helpers_1.isValidEntity)(assignment, ['name']); } async function getTasks(filter) { var _a; try { const credentials = await (0, helpers_1.getAirCredentials)(this); const options = {}; if (filter) { options.searchTerm = filter; } const response = await tasks_1.api.getTasks(this, credentials, '0', options); (0, helpers_1.validateApiResponse)(response); const allTasks = ((_a = response.result) === null || _a === void 0 ? void 0 : _a.entities) || []; return (0, helpers_1.createListSearchResults)(allTasks, isValidTask, (task) => ({ name: task.name || `Task ${task._id}`, value: extractTaskId(task), url: task.type || '', }), filter); } catch (error) { throw (0, helpers_1.catchAndFormatError)(error, 'load tasks'); } } async function getTasksOptions() { var _a; try { const credentials = await (0, helpers_1.getAirCredentials)(this); const response = await tasks_1.api.getTasks(this, credentials, '0'); (0, helpers_1.validateApiResponse)(response); const allTasks = ((_a = response.result) === null || _a === void 0 ? void 0 : _a.entities) || []; return (0, helpers_1.createLoadOptions)(allTasks, isValidTask, (task) => { const taskId = extractTaskId(task); const name = task.name || `Task ${taskId || 'Unknown'}`; return { name, value: taskId, }; }); } catch (error) { throw (0, helpers_1.catchAndFormatError)(error, 'load tasks'); } } async function executeTasks() { var _a, _b, _c, _d; const items = this.getInputData(); const returnData = []; const credentials = await (0, helpers_1.getAirCredentials)(this); for (let i = 0; i < items.length; i++) { try { const operation = this.getNodeParameter('operation', i); switch (operation) { case 'getAll': { const organizationResource = this.getNodeParameter('organizationIds', i); const additionalFields = this.getNodeParameter('additionalFields', i); let organizationIds; if (organizationResource.mode === 'list' || organizationResource.mode === 'id') { organizationIds = String(organizationResource.value); } else if (organizationResource.mode === 'name') { try { const orgId = await (0, organizations_1.findOrganizationByName)(this, credentials, organizationResource.value); organizationIds = orgId; } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, { itemIndex: i }); } } else { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid organization selection mode', { itemIndex: i, }); } const orgIds = organizationIds.trim(); if (!orgIds) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Organization IDs cannot be empty', { itemIndex: i, }); } const options = {}; if (additionalFields.pageNumber) { options.pageNumber = additionalFields.pageNumber; } if (additionalFields.pageSize) { options.pageSize = additionalFields.pageSize; } if (additionalFields.name) { options.name = additionalFields.name; } if (additionalFields.type) { options.type = additionalFields.type; } if (additionalFields.source) { options.source = additionalFields.source; } if (additionalFields.status) { options.status = additionalFields.status; } if (additionalFields.executionType) { options.executionType = additionalFields.executionType; } const response = await tasks_1.api.getTasks(this, credentials, orgIds, Object.keys(options).length > 0 ? options : undefined); (0, helpers_1.validateApiResponse)(response); const entities = ((_a = response.result) === null || _a === void 0 ? void 0 : _a.entities) || []; const paginationInfo = (0, helpers_1.extractPaginationInfo)(response.result); (0, helpers_1.processApiResponseEntities)(entities, returnData, i, { includePagination: true, paginationData: paginationInfo, excludeFields: ['sortables', 'filters'], }); break; } case 'get': { const taskId = this.getNodeParameter('taskId', i); try { (0, helpers_1.normalizeAndValidateId)(taskId, 'Task ID'); } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, { itemIndex: i, }); } const response = await tasks_1.api.getTaskById(this, credentials, taskId); if (!response.success) { const errorMessage = ((_b = response.errors) === null || _b === void 0 ? void 0 : _b.join(', ')) || 'API request failed'; throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to get task: ${errorMessage}`, { itemIndex: i, }); } if (!response.result) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Task not found', { itemIndex: i, }); } returnData.push({ json: response.result, pairedItem: i, }); break; } case 'getTaskAssignments': { const taskId = this.getNodeParameter('taskId', i); try { (0, helpers_1.normalizeAndValidateId)(taskId, 'Task ID'); } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, { itemIndex: i, }); } const response = await assignments_1.api.getTaskAssignments(this, credentials, taskId); (0, helpers_1.validateApiResponse)(response); const entities = ((_c = response.result) === null || _c === void 0 ? void 0 : _c.entities) || []; const paginationInfo = (0, helpers_1.extractPaginationInfo)(response.result); (0, helpers_1.processApiResponseEntities)(entities, returnData, i, { includePagination: true, paginationData: paginationInfo, excludeFields: ['sortables', 'filters'], }); break; } case 'waitForCompletion': { const taskId = this.getNodeParameter('taskId', i); const timeout = this.getNodeParameter('timeout', i); try { (0, helpers_1.normalizeAndValidateId)(taskId, 'Task ID'); } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, { itemIndex: i, }); } const pollingInterval = timeout === 0 ? 300000 : 60000; const startTime = Date.now(); let taskCompleted = false; while (!taskCompleted) { try { const response = await tasks_1.api.getTaskById(this, credentials, taskId); if (!response.success) { const errorMessage = ((_d = response.errors) === null || _d === void 0 ? void 0 : _d.join(', ')) || 'Failed to get task status'; throw new n8n_workflow_1.NodeOperationError(this.getNode(), errorMessage, { itemIndex: i, }); } if (!response.result) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Task not found', { itemIndex: i, }); } const task = response.result; if (task.status === 'completed') { taskCompleted = true; returnData.push({ json: { success: true, message: 'Task completed successfully', status: task.status, task: task, }, pairedItem: i, }); break; } if (task.status === 'cancelled') { returnData.push({ json: { success: false, message: 'Task was cancelled', status: task.status, error: 'Task was cancelled before completion', task: task, }, pairedItem: i, }); break; } if (task.status === 'failed') { returnData.push({ json: { success: false, message: 'Task failed', status: task.status, error: 'Task failed during execution', task: task, }, pairedItem: i, }); break; } if (timeout > 0) { const elapsedTime = (Date.now() - startTime) / 1000; if (elapsedTime >= timeout) { returnData.push({ json: { success: false, message: `Task did not complete within ${timeout} seconds`, status: task.status, error: `Timeout exceeded. Task is still in status: ${task.status}`, task: task, }, pairedItem: i, }); break; } } await new Promise(resolve => setTimeout(resolve, pollingInterval)); } catch (error) { throw error; } } break; } default: { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unknown operation: ${operation}`, { itemIndex: i, }); } } } catch (error) { (0, helpers_1.handleExecuteError)(this, error, i, returnData); } } return [returnData]; } //# sourceMappingURL=tasks.js.map