n8n-nodes-binalyze-air
Version:
Binalyze AIR nodes for automating DFIR with n8n workflows
627 lines • 25 kB
JavaScript
"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