Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@ key/
*.history
.histoy
*.vscode
.vscode
.vscode

#Other
legacy_wrapper.js
.DS_Store
334 changes: 220 additions & 114 deletions client/block.hbs

Large diffs are not rendered by default.

115 changes: 115 additions & 0 deletions client/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,54 @@ polarity.export = PolarityComponent.extend({
});
}
},
toggleIndicatorDetails: function (indicator, index) {
const indicatorPath = `details.indicators.${index}`;

if (this.get(`${indicatorPath}._indicatorDetailsLoaded`)) {
this.toggleProperty(`${indicatorPath}._indicatorDetailsOpen`);
return;
}

this.set(`${indicatorPath}._indicatorDetailsLoading`, true);

const payload = {
action: 'GET_INDICATOR_DETAILS',
indicatorId: indicator.id,
};

this.sendIntegrationMessage(payload)
.then((result) => {
const groupedMitre = this.groupMitreByTactic(result.mitre_attack_ids || []);
const relatedIocs = this.collectRelatedIocs(result.sightings || []);
const splitIocs = this.splitExtractedConfigs(relatedIocs);

result._mitreByTactic = groupedMitre;
result._relatedIocs = splitIocs.relatedIocs;
result._extractedConfigs = splitIocs.extractedConfigs;

this.set(`${indicatorPath}._indicatorDetails`, result);
this.set(`${indicatorPath}._indicatorDetailsLoaded`, true);
this.set(`${indicatorPath}._indicatorDetailsOpen`, true);
})
.catch((error) => {
console.error('Error fetching indicator details', error);
this.set(
`${indicatorPath}._indicatorDetailsError`,
JSON.stringify(error, null, 2)
);
})
.finally(() => {
this.set(`${indicatorPath}._indicatorDetailsLoading`, false);
});
},
toggleMitreGroup: function (indicatorIndex, groupIndex) {
const groupPath = `details.indicators.${indicatorIndex}._indicatorDetails._mitreByTactic.${groupIndex}._open`;
this.toggleProperty(groupPath);
},
toggleIndicatorSection: function (indicatorIndex, sectionKey) {
const sectionPath = `details.indicators.${indicatorIndex}._${sectionKey}`;
this.toggleProperty(sectionPath);
},
copyData: function () {
Ember.run.scheduleOnce(
'afterRender',
Expand Down Expand Up @@ -124,5 +172,72 @@ polarity.export = PolarityComponent.extend({
this.set('showCopyMessage', false);
}
}, 2000);
},
groupMitreByTactic(mitreAttackIds) {
const groupsByTactic = {};

mitreAttackIds.forEach((attack) => {
const tactic = attack.tactic || 'Unknown';

if (!groupsByTactic[tactic]) {
groupsByTactic[tactic] = {
tactic,
techniques: [],
_techniqueKeys: new Set(),
_open: false
};
}

const key = `${attack.name || ''}::${attack.id || ''}`;

if (!groupsByTactic[tactic]._techniqueKeys.has(key)) {
groupsByTactic[tactic]._techniqueKeys.add(key);
groupsByTactic[tactic].techniques.push({
id: attack.id,
name: attack.name
});
}
});

return Object.values(groupsByTactic)
.map((group) => {
delete group._techniqueKeys;
group.techniques.sort((a, b) =>
(a.name || '').localeCompare(b.name || '', 'en', { sensitivity: 'base' })
);
return group;
})
.sort((a, b) =>
(a.tactic || '').localeCompare(b.tactic || '', 'en', { sensitivity: 'base' })
);
},
collectRelatedIocs(sightings) {
const byKey = new Map();

sightings.forEach((sighting) => {
(sighting.related_iocs || []).forEach((ioc) => {
const key = ioc.id || ioc.href || `${ioc.type || ''}:${ioc.value || ''}`;

if (!byKey.has(key)) {
byKey.set(key, ioc);
}
});
});

return Array.from(byKey.values());
},
splitExtractedConfigs(iocs) {
const extractedConfigs = [];
const relatedIocs = [];

iocs.forEach((ioc) => {
if (ioc.type === 'extracted_config') {
extractedConfigs.push(ioc);
} else {
relatedIocs.push(ioc);
}
});

return { relatedIocs, extractedConfigs };
}
});
17 changes: 17 additions & 0 deletions client/styles.less
Original file line number Diff line number Diff line change
Expand Up @@ -303,3 +303,20 @@ pre {
}
}
}

.related-iocs-table {
width: 100%;

.type-col {
min-width: 120px;
}
}

.indicator-title {
font-weight: bold;
font-size: 1.1em;
}

.toggle-header {
margin-bottom: 6px;
}
132 changes: 0 additions & 132 deletions config/config.js

This file was deleted.

36 changes: 31 additions & 5 deletions integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,39 @@ const {
removePrivateIps,
removeEntityTypes,
getEntityTypes,
removeBlocklistedIpsAndDomains
removeBlockListedIpsAndDomains
} = require('./server/dataTransformations');
const {
getReportById,
getEvent,
getIndicators,
getReports,
getVulnerability,
getReportImage
getReportImage,
getIndicatorDetails
} = require('./server/queries');

const assembleLookupResults = require('./server/assembleLookupResults');


let Logger = null;

const startup = (logger) => {
Logger = logger;
setLogger(Logger);
};

const doLookup = async (entities, options, cb) => {
const Logger = getLogger();
try {
Logger.trace({ entities }, 'doLookup');

const entitiesWithoutBlocklistedEntities = removeBlocklistedIpsAndDomains(
const entitiesWithoutBlockListedEntities = removeBlockListedIpsAndDomains(
entities,
options
);

const searchableEntities = removePrivateIps(entitiesWithoutBlocklistedEntities);
const searchableEntities = removePrivateIps(entitiesWithoutBlockListedEntities);

const nonCveEntities = removeEntityTypes('cve', searchableEntities);
const cveEntities = getEntityTypes('cve', searchableEntities);
Expand Down Expand Up @@ -115,6 +124,23 @@ const onMessage = async (payload, options, cb) => {
cb(err);
}
break;
case 'GET_INDICATOR_DETAILS':
try {
const indicatorDetails = await getIndicatorDetails(
payload.indicatorId,
options
);
cb(null, indicatorDetails);
} catch (error) {
const err = parseErrorToReadableJson(error);

Logger.error(
{ error, formattedError: err },
'GET_INDICATOR_DETAILS Failed'
);
cb(err);
}
break;
}
};

Expand All @@ -141,7 +167,7 @@ const onDetails = async (lookupObject, options, cb) => {
};

module.exports = {
startup: setLogger,
startup,
validateOptions,
doLookup,
onDetails,
Expand Down
Loading
Loading