n8n-nodes-binalyze-air
Version:
Binalyze AIR nodes for automating DFIR with n8n workflows
1,402 lines • 59 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TriageRulesOperations = void 0;
exports.extractTriageRuleId = extractTriageRuleId;
exports.isValidTriageRule = isValidTriageRule;
exports.fetchAllTriageRules = fetchAllTriageRules;
exports.buildTriageRuleQueryParams = buildTriageRuleQueryParams;
exports.getTriageRules = getTriageRules;
exports.getTriageRulesOptions = getTriageRulesOptions;
exports.executeTriageRules = executeTriageRules;
const n8n_workflow_1 = require("n8n-workflow");
const helpers_1 = require("../utils/helpers");
const triagerules_1 = require("../api/triagerules/triagerules");
const organizations_1 = require("./organizations");
exports.TriageRulesOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
noDataExpression: true,
displayOptions: {
show: {
resource: ['triagerules'],
},
},
options: [
{
name: 'Assign Triage Task',
value: 'assignTask',
description: 'Assign a triage task',
action: 'Assign a triage task',
},
{
name: 'Create Triage Rule',
value: 'create',
description: 'Create a new triage rule',
action: 'Create a triage rule',
},
{
name: 'Delete Triage Rule',
value: 'delete',
description: 'Delete a triage rule',
action: 'Delete a triage rule',
},
{
name: 'Get',
value: 'get',
description: 'Retrieve a specific triage rule',
action: 'Get a triage rule',
},
{
name: 'Get Many',
value: 'getAll',
description: 'Retrieve many triage rules',
action: 'Get many triage rules',
},
{
name: 'Update Triage Rule',
value: 'update',
description: 'Update a triage rule',
action: 'Update a triage rule',
},
{
name: 'Validate Triage Rule',
value: 'validate',
description: 'Validate a triage rule',
action: 'Validate a triage rule',
},
],
default: 'getAll',
},
{
displayName: 'Triage Rule',
name: 'triageRuleId',
type: 'resourceLocator',
default: { mode: 'list', value: '' },
placeholder: 'Select a triage rule...',
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['get', 'update', 'delete'],
},
},
modes: [
{
displayName: 'From List',
name: 'list',
type: 'list',
placeholder: 'Select a triage rule...',
typeOptions: {
searchListMethod: 'getTriageRules',
searchable: true,
},
},
{
displayName: 'By ID',
name: 'id',
type: 'string',
validation: [
{
type: 'regex',
properties: {
regex: '^[a-zA-Z0-9-_]+$',
errorMessage: 'Not a valid triage rule ID (must contain only letters, numbers, hyphens, and underscores)',
},
},
],
placeholder: 'Enter triage rule ID',
},
],
required: true,
description: 'The triage rule to operate on',
},
{
displayName: 'Rule Engine',
name: 'engine',
type: 'options',
default: 'yara',
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['create', 'update', 'validate'],
},
},
options: [
{
name: 'YARA',
value: 'yara',
},
{
name: 'Sigma',
value: 'sigma',
},
{
name: 'Osquery',
value: 'osquery',
},
],
required: true,
description: 'The engine type for the triage rule',
},
{
displayName: 'Rule Description',
name: 'description',
type: 'string',
default: '',
placeholder: 'Enter triage rule description',
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['create', 'update'],
},
},
required: true,
description: 'Description of the triage rule (you must use spaces, hyphens, underscores, at sign or alphanumeric characters)',
typeOptions: {
validation: [
{
type: 'regex',
properties: {
regex: '^[a-zA-Z0-9 _@-]+$',
errorMessage: 'Description must contain only alphanumeric characters, spaces, hyphens, underscores, and at sign (@)',
},
},
],
},
},
{
displayName: 'Rule Content',
name: 'rule',
type: 'string',
default: '',
placeholder: 'Enter the rule content (YARA, Sigma, or osquery)',
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['create', 'update', 'validate'],
},
},
typeOptions: {
rows: 10,
},
required: true,
description: 'The rule content based on the selected engine (YARA, Sigma, or osquery)',
},
{
displayName: 'Search In',
name: 'searchIn',
type: 'options',
default: 'both',
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['create', 'update'],
engine: ['yara'],
},
},
options: [
{
name: 'File System',
value: 'filesystem',
},
{
name: 'Memory',
value: 'memory',
},
{
name: 'File System & Memory',
value: 'both',
}
],
required: true,
description: 'Where to search when running the triage rule',
},
{
displayName: 'Case ID',
name: 'caseId',
type: 'string',
default: '',
placeholder: 'Enter case ID',
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['assignTask'],
},
},
required: true,
description: 'ID of the case to assign the triage task to',
},
{
displayName: 'Triage Rule IDs',
name: 'triageRuleIds',
type: 'string',
default: '',
placeholder: 'Enter triage rule IDs (comma-separated)',
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['assignTask'],
},
},
required: true,
description: 'Comma-separated list of triage rule IDs to assign',
},
{
displayName: 'Task Choice',
name: 'taskChoice',
type: 'options',
default: 'auto',
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['assignTask'],
},
},
options: [
{
name: 'Auto',
value: 'auto',
},
{
name: 'Manual',
value: 'manual',
},
],
required: true,
description: 'Task configuration choice',
},
{
displayName: 'Enable MITRE ATT&CK',
name: 'mitreAttackEnabled',
type: 'boolean',
default: false,
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['assignTask'],
},
},
description: 'Whether to enable MITRE ATT&CK framework',
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['create'],
},
},
options: [
{
displayName: 'Organization',
name: 'organizationId',
type: 'resourceLocator',
default: { mode: 'id', value: '0' },
placeholder: 'Select an organization...',
description: 'Organization for this triage rule. Use "0" for all organizations.',
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]+$',
errorMessage: 'Not a valid organization ID (must be a positive number or 0 for default organization)',
},
},
],
placeholder: 'Enter Organization ID (0 for default organization)',
},
{
displayName: 'By Name',
name: 'name',
type: 'string',
placeholder: 'Enter organization name',
},
],
},
{
displayName: 'Rule Tag IDs',
name: 'tagIds',
type: 'string',
default: '',
placeholder: 'Enter tag IDs (comma-separated)',
description: 'Optional comma-separated list of tag IDs to associate with this triage rule',
},
],
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['getAll'],
},
},
options: [
{
displayName: 'Filter By Description',
name: 'description',
type: 'string',
default: '',
description: 'Filter triage rules by description',
},
{
displayName: 'Filter By Engines',
name: 'engines',
type: 'multiOptions',
default: [],
description: 'Filter by engine types',
options: [
{
name: 'YARA',
value: 'yara',
},
{
name: 'Sigma',
value: 'sigma',
},
{
name: 'Osquery',
value: 'osquery',
},
],
},
{
displayName: 'Filter By Search Term',
name: 'searchTerm',
type: 'string',
default: '',
description: 'Search term to filter triage rules',
},
{
displayName: 'Organization',
name: 'organizationId',
type: 'resourceLocator',
default: { mode: 'id', value: '0' },
placeholder: 'Select an organization...',
description: 'Organization to filter triage rules by. Use "0" to retrieve rules that are visible to all organizations.',
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]+$',
errorMessage: 'Not a valid organization ID (must be a positive number or 0 for default organization)',
},
},
],
placeholder: 'Enter Organization ID (0 for default organization)',
},
{
displayName: 'By Name',
name: 'name',
type: 'string',
placeholder: 'Enter organization name',
},
],
},
{
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,
},
},
],
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['get'],
},
},
options: [
{
displayName: 'Organization',
name: 'organizationId',
type: 'resourceLocator',
default: { mode: 'id', value: '0' },
placeholder: 'Select an organization...',
description: 'Organization to filter triage rules by when using "From List" selection. Use "0" to retrieve rules that are visible to all organizations.',
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]+$',
errorMessage: 'Not a valid organization ID (must be a positive number or 0 for default organization)',
},
},
],
placeholder: 'Enter Organization ID (0 for default organization)',
},
{
displayName: 'By Name',
name: 'name',
type: 'string',
placeholder: 'Enter organization name',
},
],
},
],
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['update'],
},
},
options: [
{
displayName: 'Organization',
name: 'organizationId',
type: 'resourceLocator',
default: { mode: 'id', value: '0' },
placeholder: 'Select an organization...',
description: 'Organization for this triage rule. Use "0" for all organizations.',
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]+$',
errorMessage: 'Not a valid organization ID (must be a positive number or 0 for default organization)',
},
},
],
placeholder: 'Enter Organization ID (0 for default organization)',
},
{
displayName: 'By Name',
name: 'name',
type: 'string',
placeholder: 'Enter organization name',
},
],
},
],
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: ['triagerules'],
operation: ['assignTask'],
},
},
options: [
{
displayName: 'Excluded Endpoint IDs',
name: 'excludedEndpointIds',
type: 'string',
default: '',
placeholder: 'Enter endpoint IDs (comma-separated)',
description: 'Exclude specific endpoint IDs',
},
{
displayName: 'Filter By Group Full Path',
name: 'groupFullPath',
type: 'string',
default: '',
},
{
displayName: 'Filter By Group ID',
name: 'groupId',
type: 'string',
default: '',
},
{
displayName: 'Filter By IP Address',
name: 'ipAddress',
type: 'string',
default: '',
},
{
displayName: 'Filter By Isolation Status',
name: 'isolationStatus',
type: 'multiOptions',
default: [],
options: [
{ name: 'Isolated', value: 'isolated' },
{ name: 'Not Isolated', value: 'not_isolated' },
],
},
{
displayName: 'Filter By Issue',
name: 'issue',
type: 'string',
default: '',
},
{
displayName: 'Filter By Managed Status',
name: 'managedStatus',
type: 'multiOptions',
default: [],
options: [
{ name: 'Managed', value: 'managed' },
{ name: 'Unmanaged', value: 'unmanaged' },
],
},
{
displayName: 'Filter By Name',
name: 'name',
type: 'string',
default: '',
description: 'Filter by endpoint name',
},
{
displayName: 'Filter By Online Status',
name: 'onlineStatus',
type: 'multiOptions',
default: [],
options: [
{ name: 'Online', value: 'online' },
{ name: 'Offline', value: 'offline' },
],
},
{
displayName: 'Filter By Organization',
name: 'organizationId',
type: 'resourceLocator',
default: { mode: 'id', value: '0' },
placeholder: 'Select an organization...',
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]+$',
errorMessage: 'Not a valid organization ID (must be a positive number or 0 for default organization)',
},
},
],
placeholder: 'Enter Organization ID (0 for default organization)',
},
{
displayName: 'By Name',
name: 'name',
type: 'string',
placeholder: 'Enter organization name',
},
],
},
{
displayName: 'Filter By Platform',
name: 'platform',
type: 'multiOptions',
default: [],
options: [
{ name: 'Windows', value: 'windows' },
{ name: 'Linux', value: 'linux' },
{ name: 'MacOS', value: 'macos' },
],
},
{
displayName: 'Filter By Policy',
name: 'policy',
type: 'string',
default: '',
},
{
displayName: 'Filter By Tags',
name: 'tags',
type: 'string',
default: '',
placeholder: 'Enter tags (comma-separated)',
},
{
displayName: 'Filter By Version',
name: 'version',
type: 'string',
default: '',
},
{
displayName: 'Included Endpoint IDs',
name: 'includedEndpointIds',
type: 'string',
default: '',
placeholder: 'Enter endpoint IDs (comma-separated)',
description: 'Include specific endpoint IDs',
},
{
displayName: 'Search Term',
name: 'searchTerm',
type: 'string',
default: '',
description: 'Search term to filter endpoints',
},
],
},
];
function extractTriageRuleId(triageRule) {
return (0, helpers_1.extractEntityId)(triageRule, '_id');
}
function isValidTriageRule(triageRule) {
return (0, helpers_1.isValidEntity)(triageRule, ['_id']);
}
async function fetchAllTriageRules(context, credentials, organizationIds = '0', searchFilter, pageSize = 100) {
var _a;
try {
const queryParams = {
'filter[organizationIds]': organizationIds
};
if (searchFilter) {
queryParams['filter[searchTerm]'] = searchFilter;
}
if (pageSize) {
queryParams['pageSize'] = pageSize;
}
const response = await triagerules_1.api.getTriageRules(context, credentials, organizationIds, queryParams);
return ((_a = response.result) === null || _a === void 0 ? void 0 : _a.entities) || [];
}
catch (error) {
throw (0, helpers_1.catchAndFormatError)(error, 'Failed to fetch triage rules');
}
}
function buildTriageRuleQueryParams(organizationIds, additionalFields) {
const queryParams = {
'filter[organizationIds]': organizationIds,
};
if (additionalFields.description) {
queryParams['filter[description]'] = additionalFields.description;
}
if (additionalFields.searchTerm) {
queryParams['filter[searchTerm]'] = additionalFields.searchTerm;
}
if (additionalFields.searchIn && additionalFields.searchIn.length > 0) {
queryParams['filter[searchIn]'] = additionalFields.searchIn.join(',');
}
if (additionalFields.engines && additionalFields.engines.length > 0) {
queryParams['filter[engines]'] = additionalFields.engines.join(',');
}
if (additionalFields.pageNumber) {
queryParams['pageNumber'] = additionalFields.pageNumber;
}
if (additionalFields.pageSize) {
queryParams['pageSize'] = additionalFields.pageSize;
}
return queryParams;
}
async function getTriageRules(searchTerm) {
var _a;
try {
const credentials = await (0, helpers_1.getAirCredentials)(this);
let organizationId = '0';
try {
const currentNodeParameters = this.getCurrentNodeParameters();
const additionalFields = currentNodeParameters === null || currentNodeParameters === void 0 ? void 0 : currentNodeParameters.additionalFields;
if (additionalFields === null || additionalFields === void 0 ? void 0 : additionalFields.organizationId) {
const organizationResource = additionalFields.organizationId;
let orgIdString;
if (organizationResource.mode === 'list' || organizationResource.mode === 'id') {
orgIdString = organizationResource.value;
}
else {
orgIdString = '0';
}
organizationId = (0, helpers_1.normalizeAndValidateId)(orgIdString, 'Organization ID');
}
}
catch (error) {
organizationId = '0';
}
const queryParams = {
'filter[organizationIds]': organizationId
};
if (searchTerm) {
queryParams['filter[searchTerm]'] = searchTerm;
}
const response = await triagerules_1.api.getTriageRules(this, credentials, organizationId, queryParams);
const triageRules = ((_a = response.result) === null || _a === void 0 ? void 0 : _a.entities) || [];
return (0, helpers_1.createListSearchResults)(triageRules, isValidTriageRule, (rule) => ({
name: rule.description || rule._id || 'Unknown Rule',
value: extractTriageRuleId(rule),
url: rule.url || '',
}), searchTerm);
}
catch (error) {
throw (0, helpers_1.catchAndFormatError)(error, 'Failed to load triage rules for selection');
}
}
async function getTriageRulesOptions() {
var _a;
try {
const credentials = await (0, helpers_1.getAirCredentials)(this);
const queryParams = {
'filter[organizationIds]': '0'
};
const response = await triagerules_1.api.getTriageRules(this, credentials, '0', queryParams);
const triageRules = ((_a = response.result) === null || _a === void 0 ? void 0 : _a.entities) || [];
return (0, helpers_1.createLoadOptions)(triageRules, isValidTriageRule, (rule) => {
const ruleId = extractTriageRuleId(rule);
const name = rule.description || rule._id || `Rule ${ruleId || 'Unknown'}`;
return {
name,
value: ruleId,
};
});
}
catch (error) {
throw (0, helpers_1.catchAndFormatError)(error, 'Failed to load triage rules options');
}
}
async function executeTriageRules() {
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 additionalFields = this.getNodeParameter('additionalFields', i);
let organizationId = '0';
if (additionalFields.organizationId) {
const organizationResource = additionalFields.organizationId;
let orgIdString;
if (organizationResource.mode === 'list' || organizationResource.mode === 'id') {
orgIdString = organizationResource.value;
}
else if (organizationResource.mode === 'name') {
try {
orgIdString = await (0, organizations_1.findOrganizationByName)(this, credentials, organizationResource.value);
}
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,
});
}
try {
organizationId = (0, helpers_1.normalizeAndValidateId)(orgIdString, 'Organization ID');
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, {
itemIndex: i,
});
}
}
const queryParams = buildTriageRuleQueryParams(organizationId, additionalFields);
const responseData = await triagerules_1.api.getTriageRules(this, credentials, organizationId, queryParams);
const entities = ((_a = responseData.result) === null || _a === void 0 ? void 0 : _a.entities) || [];
const paginationInfo = (0, helpers_1.extractPaginationInfo)(responseData.result);
(0, helpers_1.processApiResponseEntities)(entities, returnData, i, {
includePagination: true,
paginationData: paginationInfo,
excludeFields: ['sortables', 'filters'],
});
break;
}
case 'get': {
const triageRuleResource = this.getNodeParameter('triageRuleId', i);
let triageRuleId;
if (triageRuleResource.mode === 'list' || triageRuleResource.mode === 'id') {
triageRuleId = triageRuleResource.value;
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid triage rule selection mode', {
itemIndex: i,
});
}
try {
triageRuleId = (0, helpers_1.normalizeAndValidateId)(triageRuleId, 'Triage Rule ID');
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, {
itemIndex: i,
});
}
const responseData = await triagerules_1.api.getTriageRuleById(this, credentials, triageRuleId);
returnData.push({
json: responseData.result,
pairedItem: i,
});
break;
}
case 'create': {
const description = this.getNodeParameter('description', i);
const rule = this.getNodeParameter('rule', i);
const engine = this.getNodeParameter('engine', i);
const additionalFields = this.getNodeParameter('additionalFields', i);
let tagIds;
try {
const tagIdsString = additionalFields.tagIds;
if (tagIdsString && tagIdsString.trim()) {
tagIds = tagIdsString.split(',').map(id => id.trim()).filter(id => id.length > 0);
}
}
catch (error) {
tagIds = undefined;
}
let searchIn;
if (engine === 'yara') {
searchIn = this.getNodeParameter('searchIn', i);
}
else if (engine === 'osquery') {
searchIn = 'system';
}
else if (engine === 'sigma') {
searchIn = 'event-records';
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid triage engine ${engine}`, {
itemIndex: i,
});
}
const trimmedDescription = description.trim();
if (!trimmedDescription) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Description cannot be empty or whitespace', {
itemIndex: i,
});
}
const trimmedRule = rule.trim();
if (!trimmedRule) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Rule content cannot be empty or whitespace', {
itemIndex: i,
});
}
let organizationId = '0';
if (additionalFields.organizationId) {
const organizationResource = additionalFields.organizationId;
let orgIdString;
if (organizationResource.mode === 'list' || organizationResource.mode === 'id') {
orgIdString = organizationResource.value;
}
else if (organizationResource.mode === 'name') {
try {
orgIdString = await (0, organizations_1.findOrganizationByName)(this, credentials, organizationResource.value);
}
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,
});
}
try {
organizationId = (0, helpers_1.normalizeAndValidateId)(orgIdString, 'Organization ID');
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, {
itemIndex: i,
});
}
}
const organizationIds = [parseInt(organizationId, 10)];
const requestData = {
description: trimmedDescription,
rule: trimmedRule,
engine,
organizationIds,
searchIn,
};
if (tagIds && tagIds.length > 0) {
requestData.tagIds = tagIds;
}
try {
const responseData = await triagerules_1.api.createTriageRule(this, credentials, requestData);
if (responseData.success) {
returnData.push({
json: responseData.result,
pairedItem: i,
});
}
else {
returnData.push({
json: {
success: false,
error: true,
message: 'Failed to create triage rule',
errors: responseData.errors || [],
statusCode: responseData.statusCode || 400,
result: responseData.result || null
},
pairedItem: i,
});
}
}
catch (error) {
if ((_b = error.response) === null || _b === void 0 ? void 0 : _b.data) {
const errorData = error.response.data;
returnData.push({
json: {
success: false,
error: true,
message: errorData.message || 'Failed to create triage rule',
errors: errorData.errors || [error.message || 'Unknown validation error'],
statusCode: errorData.statusCode || error.response.status,
result: errorData.result || null
},
pairedItem: i,
});
}
else {
returnData.push({
json: {
success: false,
error: true,
message: 'Failed to create triage rule',
errors: [error.message || 'Unknown error occurred during rule creation'],
statusCode: error.statusCode || 500,
result: null
},
pairedItem: i,
});
}
}
break;
}
case 'update': {
const triageRuleResource = this.getNodeParameter('triageRuleId', i);
const description = this.getNodeParameter('description', i);
const rule = this.getNodeParameter('rule', i);
const engine = this.getNodeParameter('engine', i);
const additionalFields = this.getNodeParameter('additionalFields', i);
let searchIn;
if (engine === 'yara') {
searchIn = this.getNodeParameter('searchIn', i);
}
else if (engine === 'osquery') {
searchIn = 'system';
}
else if (engine === 'sigma') {
searchIn = 'event-records';
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Invalid triage engine ${engine}`, {
itemIndex: i,
});
}
let triageRuleId;
if (triageRuleResource.mode === 'list' || triageRuleResource.mode === 'id') {
triageRuleId = triageRuleResource.value;
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid triage rule selection mode', {
itemIndex: i,
});
}
try {
triageRuleId = (0, helpers_1.normalizeAndValidateId)(triageRuleId, 'Triage Rule ID');
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, {
itemIndex: i,
});
}
const trimmedDescription = description.trim();
if (!trimmedDescription) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Description cannot be empty or whitespace', {
itemIndex: i,
});
}
const trimmedRule = rule.trim();
if (!trimmedRule) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Rule content cannot be empty or whitespace', {
itemIndex: i,
});
}
let organizationId = '0';
if (additionalFields.organizationId) {
const organizationResource = additionalFields.organizationId;
let orgIdString;
if (organizationResource.mode === 'list' || organizationResource.mode === 'id') {
orgIdString = organizationResource.value;
}
else if (organizationResource.mode === 'name') {
try {
orgIdString = await (0, organizations_1.findOrganizationByName)(this, credentials, organizationResource.value);
}
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,
});
}
try {
organizationId = (0, helpers_1.normalizeAndValidateId)(orgIdString, 'Organization ID');
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, {
itemIndex: i,
});
}
}
const organizationIds = [parseInt(organizationId, 10)];
const requestData = {
description: trimmedDescription,
rule: trimmedRule,
organizationIds,
searchIn,
};
try {
const responseData = await triagerules_1.api.updateTriageRule(this, credentials, triageRuleId, requestData);
if (responseData.success) {
returnData.push({
json: responseData.result,
pairedItem: i,
});
}
else {
returnData.push({
json: {
success: false,
error: true,
message: 'Failed to update triage rule',
errors: responseData.errors || [],
statusCode: responseData.statusCode || 400,
result: responseData.result || null
},
pairedItem: i,
});
}
}
catch (error) {
if ((_c = error.response) === null || _c === void 0 ? void 0 : _c.data) {
const errorData = error.response.data;
returnData.push({
json: {
success: false,
error: true,
message: errorData.message || 'Failed to update triage rule',
errors: errorData.errors || [error.message || 'Unknown validation error'],
statusCode: errorData.statusCode || error.response.status,
result: errorData.result || null
},
pairedItem: i,
});
}
else {
returnData.push({
json: {
success: false,
error: true,
message: 'Failed to update triage rule',
errors: [error.message || 'Unknown error occurred during rule update'],
statusCode: error.statusCode || 500,
result: null
},
pairedItem: i,
});
}
}
break;
}
case 'delete': {
const triageRuleResource = this.getNodeParameter('triageRuleId', i);
let triageRuleId;
if (triageRuleResource.mode === 'list' || triageRuleResource.mode === 'id') {
triageRuleId = triageRuleResource.value;
}
else {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Invalid triage rule selection mode', {
itemIndex: i,
});
}
try {
triageRuleId = (0, helpers_1.normalizeAndValidateId)(triageRuleId, 'Triage Rule ID');
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, {
itemIndex: i,
});
}
await triagerules_1.api.deleteTriageRule(this, credentials, triageRuleId);
returnData.push({
json: {
success: true,
deleted: true,
id: triageRuleId,
message: 'Triage rule deleted successfully'
},
pairedItem: i,
});
break;
}
case 'validate': {
const rule = this.getNodeParameter('rule', i);
const engine = this.getNodeParameter('engine', i);
const trimmedRule = rule.trim();
if (!trimmedRule) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Rule content cannot be empty or whitespace', {
itemIndex: i,
});
}
const requestData = {
rule: trimmedRule,
engine,
};
try {
const responseData = await triagerules_1.api.validateTriageRule(this, credentials, requestData);
returnData.push({
json: {
valid: responseData.success,
errors: responseData.errors || [],
message: responseData.success ? 'Rule is valid' : 'Rule validation failed',
statusCode: responseData.statusCode,
result: responseData.result
},
pairedItem: i,
});
}
catch (error) {
if ((_d = error.response) === null || _d === void 0 ? void 0 : _d.data) {
const errorData = error.response.data;
returnData.push({
json: {
valid: false,
errors: errorData.errors || [error.message || 'Unknown validation error'],
message: 'Rule validation failed',
statusCode: errorData.statusCode || error.response.status,
result: errorData.result || null
},
pairedItem: i,
});
}
else {
returnData.push({
json: {
valid: false,
errors: [error.message || 'Unknown error occurred during validation'],
message: 'Rule validation failed',
statusCode: error.statusCode || 500,
result: null
},
pairedItem: i,
});
}
}
break;
}
case 'assignTask': {
const caseId = this.getNodeParameter('caseId', i);
const triageRuleIds = this.getNodeParameter('triageRuleIds', i);
const taskChoice = this.getNodeParameter('taskChoice', i);
const mitreAttackEnabled = this.getNodeParameter('mitreAttackEnabled', i);
const additionalFields = this.getNodeParameter('additionalFields', i);
if (!caseId.trim()) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Case ID cannot be empty', {
itemIndex: i,
});
}
if (!triageRuleIds.trim()) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), 'Triage rule IDs cannot be empty', {
itemIndex: i,
});
}
const ruleIds = triageRuleIds.split(',').map(id => id.trim()).filter(id => id.length > 0);
const filter = {};
if (additionalFields.searchTerm)
filter.searchTerm = additionalFields.searchTerm;
if (additionalFields.name)
filter.name = additionalFields.name;
if (additionalFields.ipAddress)
filter.ipAddress = additionalFields.ipAddress;
if (additionalFields.groupId)
filter.groupId = additionalFields.groupId;
if (additionalFields.groupFullPath)
filter.groupFullPath = additionalFields.groupFullPath;
if (additionalFields.managedStatus && additionalFields.managedStatus.length > 0) {
filter.managedStatus = additionalFields.managedStatus;
}
if (additionalFields.isolationStatus && additionalFields.isolationStatus.length > 0) {
filter.isolationStatus = additionalFields.isolationStatus;
}
if (additionalFields.platform && additionalFields.platform.length > 0) {
filter.platform = additionalFields.platform;
}
if (additionalFields.issue)
filter.issue = additionalFields.issue;
if (additionalFields.onlineStatus && additionalFields.onlineStatus.length > 0) {
filter.onlineStatus = additionalFields.onlineStatus;
}
if (additionalFields.tags) {
filter.tags = additionalFields.tags.split(',').map((tag) => tag.trim()).filter((tag) => tag.length > 0);
}
if (additionalFields.version)
filter.version = additionalFields.version;
if (additionalFields.policy)
filter.policy = additionalFields.policy;
if (additionalFields.includedEndpointIds) {
filter.includedEndpointIds = additionalFields.includedEndpointIds.split(',').map((id) => id.trim()).filter((id) => id.length > 0);
}
if (additionalFields.excludedEndpointIds) {
filter.excludedEndpointIds = additionalFields.excludedEndpointIds.split(',').map((id) => id.trim()).filter((id) => id.length > 0);
}
if (additionalFields.organizationId) {
const organizationResource = additionalFields.organizationId;
let orgIdString;
if (organizationResource.mode === 'list' || organizationResource.mode === 'id') {
orgIdString = organizationResource.value;
}
else if (organizationResource.mode === 'name') {
try {
orgIdString = await (0, organizations_1.findOrganizationByName)(this, credentials, organizationResource.value);
}
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,
});
}
try {
const validatedOrgId = (0, helpers_1.normalizeAndValidateId)(orgIdString, 'Organization ID');
filter.organizationIds = [parseInt(validatedOrgId, 10)];
}
catch (error) {
throw new n8n_workflow_1.NodeOperationError(this.getNode(), error.message, {
itemIndex: i,
});
}
}
const requestData = {
caseId: caseId.trim(),
triageRuleIds: ruleIds,
taskConfig: {
choice: taskChoice,
},
mitreAttack: {
enabled: mitreAttackEnabled,
},
filter,
};
const responseData = await triagerules_1.api.assignTriageTask(this, credentials, requestData);
returnData.push({
json: responseData.result,
pairedItem: i,
});
break;
}
default:
throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Unsupported operation: ${operation}`, {
itemIndex: i,
});
}
}
catch (error) {
(0, helpers_1.handleExecuteError)(this, error, i, returnData);
}
}
return [returnData];
}
//# sourceMappingURL=triagerules.js.map