From cd997c2a974d5259fb45fe51e38643254d0ea485 Mon Sep 17 00:00:00 2001 From: Charissa Miller <48832936+clemiller@users.noreply.github.com> Date: Tue, 27 Feb 2024 09:36:42 -0500 Subject: [PATCH] Fix for 620 - issues loading layers v10 and earlier (#621) * restore * bug fix 620 * bump version * update changelog * autoformatter --- CHANGELOG.md | 6 ++ nav-app/package-lock.json | 4 +- nav-app/package.json | 2 +- nav-app/src/app/classes/stix/technique.ts | 2 - nav-app/src/app/services/data.service.ts | 67 +++++++++++++---------- 5 files changed, 47 insertions(+), 34 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c1fe98d4..bab31131d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ This will patch the version number appropriately and create the correct tag on the current commit. The creation of the tag can be disabled with the --no-git-tag-version if desired. --> + +# 4.9.3 - 27 February 2024 + +## Fixes +- Fixed a bug with loading Navigator layers on ATT&CK v10 or earlier. See issue [#620](https://github.com/mitre-attack/attack-navigator/issues/620). + # 4.9.2 - 26 February 2024 ## Fixes diff --git a/nav-app/package-lock.json b/nav-app/package-lock.json index 09bc94b45..56d5c669d 100644 --- a/nav-app/package-lock.json +++ b/nav-app/package-lock.json @@ -1,12 +1,12 @@ { "name": "attack-navigator", - "version": "4.9.2", + "version": "4.9.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "attack-navigator", - "version": "4.9.2", + "version": "4.9.3", "license": "Apache-2.0", "dependencies": { "@angular/animations": "^14.3.0", diff --git a/nav-app/package.json b/nav-app/package.json index 65a2ecbdf..ebdc7129f 100644 --- a/nav-app/package.json +++ b/nav-app/package.json @@ -5,7 +5,7 @@ "type": "git", "url": "https://github.com/mitre-attack/attack-navigator.git" }, - "version": "4.9.2", + "version": "4.9.3", "license": "Apache-2.0", "scripts": { "ng": "ng", diff --git a/nav-app/src/app/classes/stix/technique.ts b/nav-app/src/app/classes/stix/technique.ts index a78c7ef44..328f2af25 100644 --- a/nav-app/src/app/classes/stix/technique.ts +++ b/nav-app/src/app/classes/stix/technique.ts @@ -8,7 +8,6 @@ export class Technique extends StixObject { public readonly subtechniques: Technique[]; // subtechniques under this technique public readonly datasources: string; // data sources of the technique public parent: Technique = null; // parent technique. Only present if it's a sub-technique - public readonly x_mitre_domains: string[]; public get isSubtechnique() { return this.parent != null; } @@ -22,7 +21,6 @@ export class Technique extends StixObject { super(stixSDO, dataService); this.platforms = stixSDO.x_mitre_platforms ? stixSDO.x_mitre_platforms.map((platform) => platform.trim()) : undefined; this.datasources = stixSDO.x_mitre_data_sources ? stixSDO.x_mitre_data_sources.toString() : ''; - this.x_mitre_domains = stixSDO.x_mitre_domains; if (!this.revoked && !this.deprecated) { this.tactics = stixSDO.kill_chain_phases.map((phase) => phase.phase_name); } diff --git a/nav-app/src/app/services/data.service.ts b/nav-app/src/app/services/data.service.ts index cc3c3f4c7..3003ab9c2 100755 --- a/nav-app/src/app/services/data.service.ts +++ b/nav-app/src/app/services/data.service.ts @@ -43,14 +43,14 @@ export class DataService { */ public parseBundle(domain: Domain, stixBundles: any[]): void { let platforms = new Set(); - let matricesList: any[] = []; - let tacticsList: any[] = []; let seenIDs = new Set(); + let matrixSDOs = []; + let idToTacticSDO = new Map(); + let matrixToTechniqueSDOs = new Map(); for (let bundle of stixBundles) { let techniqueSDOs = []; - let matrixSDOs = []; + let bundleMatrices = []; let idToTechniqueSDO = new Map(); - let idToTacticSDO = new Map(); for (let sdo of bundle.objects) { // iterate through stix domain objects in the bundle // Filter out object not included in this domain if domains field is available @@ -63,9 +63,12 @@ export class DataService { continue; } - // filter out duplicates - if (seenIDs.has(sdo.id)) continue; - seenIDs.add(sdo.id); + // filter out duplicates, except for matrices + // which are needed to properly build the datatables + if (sdo.type != 'x-mitre-matrix') { + if (seenIDs.has(sdo.id)) continue; + seenIDs.add(sdo.id); + } // parse according to type switch (sdo.type) { @@ -105,6 +108,7 @@ export class DataService { break; case 'x-mitre-matrix': matrixSDOs.push(sdo); + bundleMatrices.push(sdo); break; case 'note': domain.notes.push(new Note(sdo)); @@ -115,21 +119,21 @@ export class DataService { // create techniques this.createTechniques(techniqueSDOs, idToTechniqueSDO, domain); - // parse platforms - this.parsePlatforms(domain).forEach(platforms.add, platforms); - - // create a list of matrix and tactic SDOs - for (let matrixSDO of matrixSDOs) { - if (matrixSDO.x_mitre_deprecated) { - continue; + // create map of matrices to techniques + for (let matrixSDO of bundleMatrices) { + if (!matrixToTechniqueSDOs.get(matrixSDO.id)) { + matrixToTechniqueSDOs.set(matrixSDO.id, techniqueSDOs); + } else { + matrixToTechniqueSDOs.get(matrixSDO.id).push(...techniqueSDOs); } - matricesList.push(matrixSDO); - tacticsList.push(idToTacticSDO); } + + // parse platforms + this.parsePlatforms(domain).forEach(platforms.add, platforms); } // create matrices - this.createMatrices(matricesList, tacticsList, domain); + this.createMatrices(matrixSDOs, idToTacticSDO, matrixToTechniqueSDOs, domain); domain.platforms = Array.from(platforms); // convert to array @@ -169,18 +173,23 @@ export class DataService { * @param tacticsList list of tactic SDOs * @param domain the domain to add the matrix/tactics to */ - public createMatrices(matricesList: any[], tacticsList: any[], domain: Domain): void { - for (let i = 0; i < matricesList.length; i++) { - let techniquesList = []; - if (matricesList[i].x_mitre_deprecated) { - continue; - } - for (let technique of domain.techniques) { - if (technique.x_mitre_domains.includes(matricesList[i].external_references[0].external_id)) { - techniquesList.push(technique); - } - } - domain.matrices.push(new Matrix(matricesList[i], tacticsList[i], techniquesList, this)); + public createMatrices(matrixSDOs: any[], idToTacticSDO: Map, matrixToTechniqueSDOs, domain: Domain): void { + let createdMatrixIDs = []; + for (let matrixSDO of matrixSDOs) { + // check if matrix was already created + if (createdMatrixIDs.includes(matrixSDO.id)) continue; + + // check if matrix is deprecated + if (matrixSDO.x_mitre_deprecated) continue; + + // retrieve relevant matrix techniques + let techniqueSDOs = matrixToTechniqueSDOs.get(matrixSDO.id); + let techniqueIDs = techniqueSDOs.map((t) => t.id); + let techniques = domain.techniques.filter((t) => techniqueIDs.includes(t.id)); + domain.matrices.push(new Matrix(matrixSDO, idToTacticSDO, techniques, this)); + + // add to list of created matrices + createdMatrixIDs.push(matrixSDO.id); } }