From 94d447c60a5478f9553e09b5ef3894971e7496c7 Mon Sep 17 00:00:00 2001 From: mkouremetis Date: Mon, 8 May 2023 18:13:16 -0400 Subject: [PATCH 01/11] stashing --- app/api/definitions/openapi.yml | 3 + app/api/definitions/paths/matrices-paths.yml | 28 +++++++- app/controllers/matrices-controller.js | 24 +++++++ app/routes/matrices-routes.js | 7 ++ app/services/matrices-service.js | 68 ++++++++++++++++++++ app/services/tactics-service.js | 7 +- 6 files changed, 133 insertions(+), 4 deletions(-) diff --git a/app/api/definitions/openapi.yml b/app/api/definitions/openapi.yml index c534789f..eac4085f 100644 --- a/app/api/definitions/openapi.yml +++ b/app/api/definitions/openapi.yml @@ -120,6 +120,9 @@ paths: /api/matrices/{stixId}/modified/{modified}: $ref: 'paths/matrices-paths.yml#/paths/~1api~1matrices~1{stixId}~1modified~1{modified}' + /api/matrices/{stixId}/modified/{modified}/techniques: + $ref: 'paths/matrices-paths.yml#/paths/~1api~1matrices~1{stixId}~1modified~1{modified}~1techniques' + # Identities /api/identities: $ref: 'paths/identities-paths.yml#/paths/~1api~1identities' diff --git a/app/api/definitions/paths/matrices-paths.yml b/app/api/definitions/paths/matrices-paths.yml index 43c7d6cf..090f6219 100644 --- a/app/api/definitions/paths/matrices-paths.yml +++ b/app/api/definitions/paths/matrices-paths.yml @@ -90,7 +90,6 @@ paths: type: array items: $ref: '../components/matrices.yml#/components/schemas/matrix' - post: summary: 'Create a matrix' operationId: 'matrix-create' @@ -269,3 +268,30 @@ paths: description: 'The matrix was successfully deleted.' '404': description: 'A matrix with the requested STIX id and modified date was not found.' + + /api/matrices/{stixId}/modified/{modified}/techniques: + get: + summary: 'Retrieves techniques and subtechniques for the supplied matrix' + operationId: 'techniques-get-by-id-and-modified' + description: | + This endpoint retrieves all the techniques and subtechniques found in the supplied matrix. + tags: + - 'Matrices' + parameters: + - name: stixId + in: path + description: 'STIX id of the matrix to retrieve techniques and subtechniques' + required: true + schema: + type: string + - name: modified + in: path + description: 'modified date of the matrix to retrieve' + required: true + schema: + type: string + responses: + '200': + description: 'The techniques and subtechniques of a matrix matching the STIX id and modified date.' + '404': + description: 'A matrix with the requested STIX id and modified date was not found.' \ No newline at end of file diff --git a/app/controllers/matrices-controller.js b/app/controllers/matrices-controller.js index b45a156e..13bdeaf6 100644 --- a/app/controllers/matrices-controller.js +++ b/app/controllers/matrices-controller.js @@ -168,3 +168,27 @@ exports.deleteById = function(req, res) { } }); }; + + +exports.retrieveVersionTechniquesById = function(req, res) { + matricesService.retrieveVersionTechniquesById(req.params.stixId, req.params.modified, function (err, matrix) { + if (err) { + if (err.message === matricesService.errors.badlyFormattedParameter) { + logger.warn('Badly formatted stix id: ' + req.params.stixId); + return res.status(400).send('Stix id is badly formatted.'); + } + else { + logger.error('Failed with error: ' + err); + return res.status(500).send('Unable to get matrix techniques. Server error.'); + } + } else { + if (!matrix) { + return res.status(404).send('Matrix not found.'); + } + else { + logger.debug(`Success: Retrieved matrix techniques with id ${matrix.id}`); + return res.status(200).send(matrix); + } + } + }); +}; \ No newline at end of file diff --git a/app/routes/matrices-routes.js b/app/routes/matrices-routes.js index 5191820f..62b1a1de 100644 --- a/app/routes/matrices-routes.js +++ b/app/routes/matrices-routes.js @@ -49,4 +49,11 @@ router.route('/matrices/:stixId/modified/:modified') matricesController.deleteVersionById ); +router.route('/matrices/:stixId/modified/:modified/techniques') + .get( + authn.authenticate, + authz.requireRole(authz.visitorOrHigher, authz.readOnlyService), + matricesController.retrieveVersionTechniquesById + ); + module.exports = router; diff --git a/app/services/matrices-service.js b/app/services/matrices-service.js index 72ebbb04..b79ef08a 100644 --- a/app/services/matrices-service.js +++ b/app/services/matrices-service.js @@ -1,6 +1,7 @@ 'use strict'; const uuid = require('uuid'); +const util = require('util'); const Matrix = require('../models/matrix-model'); const systemConfigurationService = require('./system-configuration-service'); const identitiesService = require('./identities-service'); @@ -213,6 +214,71 @@ exports.retrieveVersionById = function(stixId, modified, callback) { }); }; +let retrieveTacticById; +let retrieveTechniquesForTactic; +exports.retrieveVersionTechniquesById = async function(stixId, modified, callback) { + // Retrieve the versions of the matrix techniques with the matching stixId and modified date + + // Late binding to avoid circular dependency between modules + if (!retrieveTacticById) { + const tacticsService = require('./tactics-service'); + retrieveTacticById = util.promisify(tacticsService.retrieveById); + } + if (!retrieveTechniquesForTactic) { + const tacticsService = require('./tactics-service'); + retrieveTechniquesForTactic = util.promisify(tacticsService.retrieveTechniquesForTactic); + } + + if (!stixId) { + const error = new Error(errors.missingParameter); + error.parameterName = 'stixId'; + return callback(error); + } + + if (!modified) { + const error = new Error(errors.missingParameter); + error.parameterName = 'modified'; + return callback(error); + } + + Matrix.findOne({ 'stix.id': stixId, 'stix.modified': modified }, async function(err, matrix) { + if (err) { + if (err.name === 'CastError') { + const error = new Error(errors.badlyFormattedParameter); + error.parameterName = 'stixId'; + return callback(error); + } + else { + return callback(err); + } + } + else { + if (matrix) { + // get tactics, query for techniques and sub-techniques + console.log('-------'); + const options = {versions: 'latest' }; + let tactics_techniques = {}; + for (const tactic_id of matrix['stix']['tactic_refs']) { + let tactic = await retrieveTacticById(tactic_id, options); + if (tactic) { + let tactic_name = tactic[0]['stix']['name']; + tactics_techniques[tactic_name] = tactic; + console.error("retrieving techniques"); + let techniques = await retrieveTechniquesForTactic(tactic_id, tactic[0]['stix']['modified'], options); + console.log(techniques); + tactics_techniques[tactic_name]['techniques'] = techniques; + } + } + return callback(null, tactics_techniques); + } + else { + console.log('** NOT FOUND'); + return callback(); + } + } + }); +}; + exports.createIsAsync = true; exports.create = async function(data, options) { // This function handles two use cases: @@ -369,3 +435,5 @@ exports.deleteById = function (stixId, callback) { }); }; + + diff --git a/app/services/tactics-service.js b/app/services/tactics-service.js index 1df10755..cd0197b7 100644 --- a/app/services/tactics-service.js +++ b/app/services/tactics-service.js @@ -415,10 +415,8 @@ exports.retrieveTechniquesForTactic = async function(stixId, modified, options) error.parameterName = 'modified'; throw error; } - try { const tactic = await Tactic.findOne({ 'stix.id': stixId, 'stix.modified': modified }); - // Note: document is null if not found if (!tactic) { return null; @@ -426,8 +424,9 @@ exports.retrieveTechniquesForTactic = async function(stixId, modified, options) else { const allTechniques = await retrieveAllTechniques({}); const filteredTechniques = allTechniques.filter(techniqueMatchesTactic(tactic)); + console.log("filtering techniques"); const pagedResults = getPageOfData(filteredTechniques, options); - + console.log("got paged results"); if (options.includePagination) { const returnValue = { pagination: { @@ -437,9 +436,11 @@ exports.retrieveTechniquesForTactic = async function(stixId, modified, options) }, data: pagedResults }; + console.log("returning"); return returnValue; } else { + console.log("returning 2"); return pagedResults; } } From a18b5a69c3a84973dac2ccd0e737e140d0d3b52d Mon Sep 17 00:00:00 2001 From: mkouremetis Date: Wed, 10 May 2023 13:46:08 -0400 Subject: [PATCH 02/11] stashing for further debugging --- app/services/matrices-service.js | 22 ++++++++++++++-------- app/services/tactics-service.js | 8 +++----- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/app/services/matrices-service.js b/app/services/matrices-service.js index b79ef08a..57722372 100644 --- a/app/services/matrices-service.js +++ b/app/services/matrices-service.js @@ -255,18 +255,24 @@ exports.retrieveVersionTechniquesById = async function(stixId, modified, callbac else { if (matrix) { // get tactics, query for techniques and sub-techniques - console.log('-------'); - const options = {versions: 'latest' }; + const options = {versions: 'latest', offset: 0, limit: 0 }; let tactics_techniques = {}; + for (const tactic_id of matrix['stix']['tactic_refs']) { + let tactic = await retrieveTacticById(tactic_id, options); + console.log(tactic[0]['stix']['name']); + console.log('------'); + } for (const tactic_id of matrix['stix']['tactic_refs']) { let tactic = await retrieveTacticById(tactic_id, options); if (tactic) { - let tactic_name = tactic[0]['stix']['name']; - tactics_techniques[tactic_name] = tactic; - console.error("retrieving techniques"); - let techniques = await retrieveTechniquesForTactic(tactic_id, tactic[0]['stix']['modified'], options); - console.log(techniques); - tactics_techniques[tactic_name]['techniques'] = techniques; + tactic = tactic[0]; + console.log(tactic); + let techniques = await retrieveTechniquesForTactic(tactic_id, tactic['stix']['modified'], options); + console.log(techniques.length); //Never gets here, why? + tactic['techniques'] = techniques; + tactics_techniques[tactic[0]['stix']['name']] = tactic; + console.log(tactics_techniques); + console.log('end of loop'); } } return callback(null, tactics_techniques); diff --git a/app/services/tactics-service.js b/app/services/tactics-service.js index cd0197b7..e7cd5de6 100644 --- a/app/services/tactics-service.js +++ b/app/services/tactics-service.js @@ -391,7 +391,6 @@ function techniqueMatchesTactic(tactic) { function getPageOfData(data, options) { const startPos = options.offset; const endPos = (options.limit === 0) ? data.length : Math.min(options.offset + options.limit, data.length); - return data.slice(startPos, endPos); } @@ -424,9 +423,9 @@ exports.retrieveTechniquesForTactic = async function(stixId, modified, options) else { const allTechniques = await retrieveAllTechniques({}); const filteredTechniques = allTechniques.filter(techniqueMatchesTactic(tactic)); - console.log("filtering techniques"); + console.log(filteredTechniques.length); const pagedResults = getPageOfData(filteredTechniques, options); - console.log("got paged results"); + console.log(pagedResults.length); if (options.includePagination) { const returnValue = { pagination: { @@ -436,11 +435,10 @@ exports.retrieveTechniquesForTactic = async function(stixId, modified, options) }, data: pagedResults }; - console.log("returning"); return returnValue; } else { - console.log("returning 2"); + console.log('Returning--'); return pagedResults; } } From 2528f6b653058581ef3426b04fc0dc14af629272 Mon Sep 17 00:00:00 2001 From: mkouremetis Date: Mon, 15 May 2023 09:23:11 -0400 Subject: [PATCH 03/11] basic endpoint operation working --- app/services/matrices-service.js | 14 +++----------- app/services/tactics-service.js | 3 --- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/app/services/matrices-service.js b/app/services/matrices-service.js index 57722372..4f481b13 100644 --- a/app/services/matrices-service.js +++ b/app/services/matrices-service.js @@ -226,7 +226,7 @@ exports.retrieveVersionTechniquesById = async function(stixId, modified, callbac } if (!retrieveTechniquesForTactic) { const tacticsService = require('./tactics-service'); - retrieveTechniquesForTactic = util.promisify(tacticsService.retrieveTechniquesForTactic); + retrieveTechniquesForTactic = tacticsService.retrieveTechniquesForTactic; } if (!stixId) { @@ -257,23 +257,15 @@ exports.retrieveVersionTechniquesById = async function(stixId, modified, callbac // get tactics, query for techniques and sub-techniques const options = {versions: 'latest', offset: 0, limit: 0 }; let tactics_techniques = {}; - for (const tactic_id of matrix['stix']['tactic_refs']) { - let tactic = await retrieveTacticById(tactic_id, options); - console.log(tactic[0]['stix']['name']); - console.log('------'); - } for (const tactic_id of matrix['stix']['tactic_refs']) { let tactic = await retrieveTacticById(tactic_id, options); if (tactic) { tactic = tactic[0]; - console.log(tactic); let techniques = await retrieveTechniquesForTactic(tactic_id, tactic['stix']['modified'], options); - console.log(techniques.length); //Never gets here, why? tactic['techniques'] = techniques; - tactics_techniques[tactic[0]['stix']['name']] = tactic; - console.log(tactics_techniques); - console.log('end of loop'); + tactics_techniques[tactic['stix']['name']] = tactic; } + return callback(null, tactics_techniques); } return callback(null, tactics_techniques); } diff --git a/app/services/tactics-service.js b/app/services/tactics-service.js index e7cd5de6..2a171ffe 100644 --- a/app/services/tactics-service.js +++ b/app/services/tactics-service.js @@ -423,9 +423,7 @@ exports.retrieveTechniquesForTactic = async function(stixId, modified, options) else { const allTechniques = await retrieveAllTechniques({}); const filteredTechniques = allTechniques.filter(techniqueMatchesTactic(tactic)); - console.log(filteredTechniques.length); const pagedResults = getPageOfData(filteredTechniques, options); - console.log(pagedResults.length); if (options.includePagination) { const returnValue = { pagination: { @@ -438,7 +436,6 @@ exports.retrieveTechniquesForTactic = async function(stixId, modified, options) return returnValue; } else { - console.log('Returning--'); return pagedResults; } } From 9795b96390dcc88360c40eadc67bac415d9bce45 Mon Sep 17 00:00:00 2001 From: mkouremetis Date: Mon, 15 May 2023 16:34:32 -0400 Subject: [PATCH 04/11] nested subtechniques --- app/services/matrices-service.js | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/app/services/matrices-service.js b/app/services/matrices-service.js index 4f481b13..c5936af1 100644 --- a/app/services/matrices-service.js +++ b/app/services/matrices-service.js @@ -262,10 +262,29 @@ exports.retrieveVersionTechniquesById = async function(stixId, modified, callbac if (tactic) { tactic = tactic[0]; let techniques = await retrieveTechniquesForTactic(tactic_id, tactic['stix']['modified'], options); - tactic['techniques'] = techniques; + // Organize sub-techniques under super techniques + let super_techniques = []; + let sub_techniques = []; + for (const technique of techniques) { + if (technique['stix']['x_mitre_is_subtechnique'] === false) { + super_techniques.push(technique); + } + else { + sub_techniques.push(technique); + } + } + for (const super_technique of super_techniques) { + super_technique['subtechniques'] = []; + for (const sub_technique of sub_techniques) { + if (sub_technique['workspace']['attack_id'].split(".")[0] === super_technique['workspace']['attack_id']) { + super_technique['subtechniques'].push(sub_technique); + } + } + } + // Add techniques to tactic + tactic['techniques'] = super_techniques; tactics_techniques[tactic['stix']['name']] = tactic; } - return callback(null, tactics_techniques); } return callback(null, tactics_techniques); } From e2c203f36915341b82eb54a8f14b126b295855b2 Mon Sep 17 00:00:00 2001 From: mkouremetis Date: Mon, 15 May 2023 16:38:49 -0400 Subject: [PATCH 05/11] syntax --- app/services/matrices-service.js | 4 ++-- app/services/tactics-service.js | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/services/matrices-service.js b/app/services/matrices-service.js index c5936af1..cdf96f67 100644 --- a/app/services/matrices-service.js +++ b/app/services/matrices-service.js @@ -254,8 +254,8 @@ exports.retrieveVersionTechniquesById = async function(stixId, modified, callbac } else { if (matrix) { - // get tactics, query for techniques and sub-techniques - const options = {versions: 'latest', offset: 0, limit: 0 }; + // get tactics, then query for techniques and sub-techniques + const options = { versions: 'latest', offset: 0, limit: 0 }; let tactics_techniques = {}; for (const tactic_id of matrix['stix']['tactic_refs']) { let tactic = await retrieveTacticById(tactic_id, options); diff --git a/app/services/tactics-service.js b/app/services/tactics-service.js index 2a171ffe..1df10755 100644 --- a/app/services/tactics-service.js +++ b/app/services/tactics-service.js @@ -391,6 +391,7 @@ function techniqueMatchesTactic(tactic) { function getPageOfData(data, options) { const startPos = options.offset; const endPos = (options.limit === 0) ? data.length : Math.min(options.offset + options.limit, data.length); + return data.slice(startPos, endPos); } @@ -414,8 +415,10 @@ exports.retrieveTechniquesForTactic = async function(stixId, modified, options) error.parameterName = 'modified'; throw error; } + try { const tactic = await Tactic.findOne({ 'stix.id': stixId, 'stix.modified': modified }); + // Note: document is null if not found if (!tactic) { return null; @@ -424,6 +427,7 @@ exports.retrieveTechniquesForTactic = async function(stixId, modified, options) const allTechniques = await retrieveAllTechniques({}); const filteredTechniques = allTechniques.filter(techniqueMatchesTactic(tactic)); const pagedResults = getPageOfData(filteredTechniques, options); + if (options.includePagination) { const returnValue = { pagination: { From e7e9de47b4dbd517fb3a2bfca5988b84d943669e Mon Sep 17 00:00:00 2001 From: mkouremetis Date: Mon, 15 May 2023 16:41:30 -0400 Subject: [PATCH 06/11] syntax --- app/api/definitions/paths/matrices-paths.yml | 2 +- app/controllers/matrices-controller.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/api/definitions/paths/matrices-paths.yml b/app/api/definitions/paths/matrices-paths.yml index 090f6219..d4d03625 100644 --- a/app/api/definitions/paths/matrices-paths.yml +++ b/app/api/definitions/paths/matrices-paths.yml @@ -294,4 +294,4 @@ paths: '200': description: 'The techniques and subtechniques of a matrix matching the STIX id and modified date.' '404': - description: 'A matrix with the requested STIX id and modified date was not found.' \ No newline at end of file + description: 'A matrix with the requested STIX id and modified date was not found.' diff --git a/app/controllers/matrices-controller.js b/app/controllers/matrices-controller.js index 13bdeaf6..3b1da72b 100644 --- a/app/controllers/matrices-controller.js +++ b/app/controllers/matrices-controller.js @@ -191,4 +191,4 @@ exports.retrieveVersionTechniquesById = function(req, res) { } } }); -}; \ No newline at end of file +}; From bf6a4c654d97af29b26eb68826ea3a1adfe6895e Mon Sep 17 00:00:00 2001 From: mkouremetis Date: Wed, 17 May 2023 10:31:27 -0400 Subject: [PATCH 07/11] extra newlines --- app/services/matrices-service.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/services/matrices-service.js b/app/services/matrices-service.js index cdf96f67..6b37a410 100644 --- a/app/services/matrices-service.js +++ b/app/services/matrices-service.js @@ -451,6 +451,3 @@ exports.deleteById = function (stixId, callback) { } }); }; - - - From 93b8e85476ddbbb7e88fec89d46efc38a64e24f2 Mon Sep 17 00:00:00 2001 From: mkouremetis Date: Wed, 17 May 2023 10:37:56 -0400 Subject: [PATCH 08/11] review --- app/services/matrices-service.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/services/matrices-service.js b/app/services/matrices-service.js index 6b37a410..6d609da6 100644 --- a/app/services/matrices-service.js +++ b/app/services/matrices-service.js @@ -234,7 +234,6 @@ exports.retrieveVersionTechniquesById = async function(stixId, modified, callbac error.parameterName = 'stixId'; return callback(error); } - if (!modified) { const error = new Error(errors.missingParameter); error.parameterName = 'modified'; @@ -281,7 +280,7 @@ exports.retrieveVersionTechniquesById = async function(stixId, modified, callbac } } } - // Add techniques to tactic + // Add techniques to tactic & store tactic tactic['techniques'] = super_techniques; tactics_techniques[tactic['stix']['name']] = tactic; } From 827f993f423c6b263bde2439abd37372c63231a3 Mon Sep 17 00:00:00 2001 From: mkouremetis Date: Wed, 17 May 2023 10:43:51 -0400 Subject: [PATCH 09/11] playing the sonarcloud game --- app/services/matrices-service.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/services/matrices-service.js b/app/services/matrices-service.js index 6d609da6..f9aac57f 100644 --- a/app/services/matrices-service.js +++ b/app/services/matrices-service.js @@ -216,6 +216,7 @@ exports.retrieveVersionById = function(stixId, modified, callback) { let retrieveTacticById; let retrieveTechniquesForTactic; +exports.retrieveVersionTechniquesById = true; exports.retrieveVersionTechniquesById = async function(stixId, modified, callback) { // Retrieve the versions of the matrix techniques with the matching stixId and modified date From 5a72a1a496a47a42581cf9832c96634953b603a0 Mon Sep 17 00:00:00 2001 From: mkouremetis Date: Wed, 17 May 2023 11:09:11 -0400 Subject: [PATCH 10/11] same as last --- app/controllers/matrices-controller.js | 4 ++-- app/services/matrices-service.js | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/app/controllers/matrices-controller.js b/app/controllers/matrices-controller.js index 3b1da72b..078ffd33 100644 --- a/app/controllers/matrices-controller.js +++ b/app/controllers/matrices-controller.js @@ -170,8 +170,8 @@ exports.deleteById = function(req, res) { }; -exports.retrieveVersionTechniquesById = function(req, res) { - matricesService.retrieveVersionTechniquesById(req.params.stixId, req.params.modified, function (err, matrix) { +exports.retrieveVersionTechniquesById = async function(req, res) { + await matricesService.retrieveVersionTechniquesById(req.params.stixId, req.params.modified, function (err, matrix) { if (err) { if (err.message === matricesService.errors.badlyFormattedParameter) { logger.warn('Badly formatted stix id: ' + req.params.stixId); diff --git a/app/services/matrices-service.js b/app/services/matrices-service.js index f9aac57f..7a648a68 100644 --- a/app/services/matrices-service.js +++ b/app/services/matrices-service.js @@ -216,7 +216,6 @@ exports.retrieveVersionById = function(stixId, modified, callback) { let retrieveTacticById; let retrieveTechniquesForTactic; -exports.retrieveVersionTechniquesById = true; exports.retrieveVersionTechniquesById = async function(stixId, modified, callback) { // Retrieve the versions of the matrix techniques with the matching stixId and modified date @@ -256,15 +255,15 @@ exports.retrieveVersionTechniquesById = async function(stixId, modified, callbac if (matrix) { // get tactics, then query for techniques and sub-techniques const options = { versions: 'latest', offset: 0, limit: 0 }; - let tactics_techniques = {}; + const tactics_techniques = {}; for (const tactic_id of matrix['stix']['tactic_refs']) { let tactic = await retrieveTacticById(tactic_id, options); if (tactic) { tactic = tactic[0]; - let techniques = await retrieveTechniquesForTactic(tactic_id, tactic['stix']['modified'], options); + const techniques = await retrieveTechniquesForTactic(tactic_id, tactic['stix']['modified'], options); // Organize sub-techniques under super techniques - let super_techniques = []; - let sub_techniques = []; + const super_techniques = []; + const sub_techniques = []; for (const technique of techniques) { if (technique['stix']['x_mitre_is_subtechnique'] === false) { super_techniques.push(technique); From d973f8d9dff7f485893af67f5799ec2c9d3b2339 Mon Sep 17 00:00:00 2001 From: Jack Sheriff Date: Wed, 31 May 2023 12:58:13 -0400 Subject: [PATCH 11/11] Modify variable naming to be more consistent with existing code. Remove unneeded async function attributions. --- app/controllers/matrices-controller.js | 13 ++++---- app/routes/matrices-routes.js | 2 +- app/services/matrices-service.js | 45 +++++++++++++------------- 3 files changed, 29 insertions(+), 31 deletions(-) diff --git a/app/controllers/matrices-controller.js b/app/controllers/matrices-controller.js index 078ffd33..b969fbd2 100644 --- a/app/controllers/matrices-controller.js +++ b/app/controllers/matrices-controller.js @@ -169,9 +169,8 @@ exports.deleteById = function(req, res) { }); }; - -exports.retrieveVersionTechniquesById = async function(req, res) { - await matricesService.retrieveVersionTechniquesById(req.params.stixId, req.params.modified, function (err, matrix) { +exports.retrieveTechniquesForMatrix = function(req, res) { + matricesService.retrieveTechniquesForMatrix(req.params.stixId, req.params.modified, function (err, techniquesByTactic) { if (err) { if (err.message === matricesService.errors.badlyFormattedParameter) { logger.warn('Badly formatted stix id: ' + req.params.stixId); @@ -179,15 +178,15 @@ exports.retrieveVersionTechniquesById = async function(req, res) { } else { logger.error('Failed with error: ' + err); - return res.status(500).send('Unable to get matrix techniques. Server error.'); + return res.status(500).send('Unable to get techniques for matrix. Server error.'); } } else { - if (!matrix) { + if (!techniquesByTactic) { return res.status(404).send('Matrix not found.'); } else { - logger.debug(`Success: Retrieved matrix techniques with id ${matrix.id}`); - return res.status(200).send(matrix); + logger.debug(`Success: Retrieved techniques for matrix with id ${ req.params.stixId }`); + return res.status(200).send(techniquesByTactic); } } }); diff --git a/app/routes/matrices-routes.js b/app/routes/matrices-routes.js index 62b1a1de..c666f09b 100644 --- a/app/routes/matrices-routes.js +++ b/app/routes/matrices-routes.js @@ -53,7 +53,7 @@ router.route('/matrices/:stixId/modified/:modified/techniques') .get( authn.authenticate, authz.requireRole(authz.visitorOrHigher, authz.readOnlyService), - matricesController.retrieveVersionTechniquesById + matricesController.retrieveTechniquesForMatrix ); module.exports = router; diff --git a/app/services/matrices-service.js b/app/services/matrices-service.js index 7a648a68..b5dd6312 100644 --- a/app/services/matrices-service.js +++ b/app/services/matrices-service.js @@ -216,7 +216,7 @@ exports.retrieveVersionById = function(stixId, modified, callback) { let retrieveTacticById; let retrieveTechniquesForTactic; -exports.retrieveVersionTechniquesById = async function(stixId, modified, callback) { +exports.retrieveTechniquesForMatrix = function(stixId, modified, callback) { // Retrieve the versions of the matrix techniques with the matching stixId and modified date // Late binding to avoid circular dependency between modules @@ -239,7 +239,7 @@ exports.retrieveVersionTechniquesById = async function(stixId, modified, callbac error.parameterName = 'modified'; return callback(error); } - + Matrix.findOne({ 'stix.id': stixId, 'stix.modified': modified }, async function(err, matrix) { if (err) { if (err.name === 'CastError') { @@ -255,40 +255,39 @@ exports.retrieveVersionTechniquesById = async function(stixId, modified, callbac if (matrix) { // get tactics, then query for techniques and sub-techniques const options = { versions: 'latest', offset: 0, limit: 0 }; - const tactics_techniques = {}; - for (const tactic_id of matrix['stix']['tactic_refs']) { - let tactic = await retrieveTacticById(tactic_id, options); - if (tactic) { - tactic = tactic[0]; - const techniques = await retrieveTechniquesForTactic(tactic_id, tactic['stix']['modified'], options); - // Organize sub-techniques under super techniques - const super_techniques = []; - const sub_techniques = []; + const tacticsTechniques = {}; + for (const tacticId of matrix.stix.tactic_refs) { + const tactics = await retrieveTacticById(tacticId, options); + if (tactics.length) { + const tactic = tactics[0]; + const techniques = await retrieveTechniquesForTactic(tacticId, tactic.stix.modified, options); + // Organize sub-techniques under parent techniques + const parentTechniques = []; + const subtechniques = []; for (const technique of techniques) { - if (technique['stix']['x_mitre_is_subtechnique'] === false) { - super_techniques.push(technique); + if (!technique.stix.x_mitre_is_subtechnique) { + parentTechniques.push(technique); } else { - sub_techniques.push(technique); + subtechniques.push(technique); } } - for (const super_technique of super_techniques) { - super_technique['subtechniques'] = []; - for (const sub_technique of sub_techniques) { - if (sub_technique['workspace']['attack_id'].split(".")[0] === super_technique['workspace']['attack_id']) { - super_technique['subtechniques'].push(sub_technique); + for (const parentTechnique of parentTechniques) { + parentTechnique.subtechniques = []; + for (const subtechnique of subtechniques) { + if (subtechnique.workspace.attack_id.split(".")[0] === parentTechnique.workspace.attack_id) { + parentTechnique.subtechniques.push(subtechnique); } } } // Add techniques to tactic & store tactic - tactic['techniques'] = super_techniques; - tactics_techniques[tactic['stix']['name']] = tactic; + tactic.techniques = parentTechniques; + tacticsTechniques[tactic.stix.name] = tactic; } } - return callback(null, tactics_techniques); + return callback(null, tacticsTechniques); } else { - console.log('** NOT FOUND'); return callback(); } }