From d9c6be40e95caafed3c2d340ad5357d7a41e144e Mon Sep 17 00:00:00 2001 From: Charissa Miller <48832936+clemiller@users.noreply.github.com> Date: Sun, 25 Feb 2024 08:35:11 -0500 Subject: [PATCH 01/39] load collection index --- nav-app/src/app/services/config.service.ts | 70 ++++--- nav-app/src/assets/config.json | 213 +-------------------- 2 files changed, 43 insertions(+), 240 deletions(-) diff --git a/nav-app/src/app/services/config.service.ts b/nav-app/src/app/services/config.service.ts index 373895720..1a5b350bc 100644 --- a/nav-app/src/app/services/config.service.ts +++ b/nav-app/src/app/services/config.service.ts @@ -1,11 +1,14 @@ import { Injectable } from '@angular/core'; import { ContextMenuItem } from '../classes/context-menu-item'; import { HttpClient } from '@angular/common/http'; +import { map, switchMap } from 'rxjs/operators'; +import { of } from 'rxjs'; @Injectable({ providedIn: 'root', }) export class ConfigService { + public collectionIndex: string; public versions: any[] = []; public contextMenuItems: ContextMenuItem[] = []; public defaultLayers: any; @@ -172,34 +175,43 @@ export class ConfigService { * Note: this is done at startup */ public loadConfig() { - return this.http - .get('./assets/config.json') - .toPromise() - .then((config) => { - console.debug(`loaded app configuration settings`); - - this.versions = config['versions']; - config['custom_context_menu_items'].forEach((item) => { - this.contextMenuItems.push(new ContextMenuItem(item.label, item.url, item.subtechnique_url)); - }); - this.defaultLayers = config['default_layers']; - this.commentColor = config['comment_color']; - this.linkColor = config['link_color']; - this.metadataColor = config['metadata_color']; - this.banner = config['banner']; - - // parse feature preferences - this.featureList = config['features']; - config['features'].forEach((feature) => { - this.setFeature_object(feature); - }); - - // override preferences with preferences from URL fragments - this.getAllFragments().forEach((value: string, key: string) => { - if (this.isFeature(key) || this.isFeatureGroup(key)) { - this.setFeature(key, value == 'true'); - } - }); - }); + return this.http.get('./assets/config.json').pipe( + map((config) => { + console.debug('loaded app configuration settings'); + + this.versions = config['versions']; + + config['custom_context_menu_items'].forEach((item) => { + this.contextMenuItems.push(new ContextMenuItem(item.label, item.url, item.subtechnique_url)); + }); + this.defaultLayers = config['default_layers']; + this.commentColor = config['comment_color']; + this.linkColor = config['link_color']; + this.metadataColor = config['metadata_color']; + this.banner = config['banner']; + + // parse feature preferences + this.featureList = config['features']; + config['features'].forEach((feature) => { + this.setFeature_object(feature); + }); + + // override preferences with preferences from URL fragments + this.getAllFragments().forEach((value: string, key: string) => { + if (this.isFeature(key) || this.isFeatureGroup(key)) { + this.setFeature(key, value == 'true'); + } + }); + return config['collection_index_url']; + }), + switchMap((collectionIndexUrl: string) => { + if (collectionIndexUrl) return this.http.get(collectionIndexUrl); + return of({}); + }), + map((collectionIndex: any) => { + console.log('loaded collection index'); + this.collectionIndex = collectionIndex; + }) + ).toPromise() } } diff --git a/nav-app/src/assets/config.json b/nav-app/src/assets/config.json index 44271d80e..66248cb08 100755 --- a/nav-app/src/assets/config.json +++ b/nav-app/src/assets/config.json @@ -1,216 +1,7 @@ { + "collection_index_url": "https://raw.githubusercontent.com/mitre-attack/attack-stix-data/master/index.json", + "versions": [ - { - "name": "ATT&CK v14", - "version": "14", - "domains": [ - { - "name": "Enterprise", - "identifier": "enterprise-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v14.1/enterprise-attack/enterprise-attack.json"] - }, - { - "name": "Mobile", - "identifier": "mobile-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v14.1/mobile-attack/mobile-attack.json"] - }, - { - "name": "ICS", - "identifier": "ics-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v14.1/ics-attack/ics-attack.json"] - } - ] - }, - { - "name": "ATT&CK v13", - "version": "13", - "domains": [ - { - "name": "Enterprise", - "identifier": "enterprise-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v13.1/enterprise-attack/enterprise-attack.json"] - }, - { - "name": "Mobile", - "identifier": "mobile-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v13.1/mobile-attack/mobile-attack.json"] - }, - { - "name": "ICS", - "identifier": "ics-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v13.1/ics-attack/ics-attack.json"] - } - ] - }, - { - "name": "ATT&CK v12", - "version": "12", - "domains": [ - { - "name": "Enterprise", - "identifier": "enterprise-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v12.1/enterprise-attack/enterprise-attack.json"] - }, - { - "name": "Mobile", - "identifier": "mobile-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v12.1/mobile-attack/mobile-attack.json"] - }, - { - "name": "ICS", - "identifier": "ics-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v12.1/ics-attack/ics-attack.json"] - } - ] - }, - { - "name": "ATT&CK v11", - "version": "11", - "domains": [ - { - "name": "Enterprise", - "identifier": "enterprise-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v11.3/enterprise-attack/enterprise-attack.json"] - }, - { - "name": "Mobile", - "identifier": "mobile-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v11.3/mobile-attack/mobile-attack.json"] - }, - { - "name": "ICS", - "identifier": "ics-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v11.3/ics-attack/ics-attack.json"] - } - ] - }, - { - "name": "ATT&CK v10", - "version": "10", - "domains": [ - { - "name": "Enterprise", - "identifier": "enterprise-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v10.1/enterprise-attack/enterprise-attack.json"] - }, - { - "name": "Mobile", - "identifier": "mobile-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v10.1/mobile-attack/mobile-attack.json"] - }, - { - "name": "ICS", - "identifier": "ics-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v10.1/ics-attack/ics-attack.json"] - } - ] - }, - { - "name": "ATT&CK v9", - "version": "9", - "domains": [ - { - "name": "Enterprise", - "identifier": "enterprise-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v9.0/enterprise-attack/enterprise-attack.json"] - }, - { - "name": "Mobile", - "identifier": "mobile-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v9.0/mobile-attack/mobile-attack.json"] - }, - { - "name": "ICS", - "identifier": "ics-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v9.0/ics-attack/ics-attack.json"] - } - ] - }, - { - "name": "ATT&CK v8", - "version": "8", - "domains": [ - { - "name": "Enterprise", - "identifier": "enterprise-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v8.2/enterprise-attack/enterprise-attack.json"] - }, - { - "name": "Mobile", - "identifier": "mobile-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v8.2/mobile-attack/mobile-attack.json"] - }, - { - "name": "ICS", - "identifier": "ics-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v8.2/ics-attack/ics-attack.json"] - } - ] - }, - { - "name": "ATT&CK v7", - "version": "7", - "domains": [ - { - "name": "Enterprise", - "identifier": "enterprise-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v7.2/enterprise-attack/enterprise-attack.json"] - }, - { - "name": "Mobile", - "identifier": "mobile-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v7.2/mobile-attack/mobile-attack.json"] - } - ] - }, - { - "name": "ATT&CK v6", - "version": "6", - "domains": [ - { - "name": "Enterprise", - "identifier": "enterprise-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v6.3/enterprise-attack/enterprise-attack.json"] - }, - { - "name": "Mobile", - "identifier": "mobile-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v6.3/mobile-attack/mobile-attack.json"] - } - ] - }, - { - "name": "ATT&CK v5", - "version": "5", - "domains": [ - { - "name": "Enterprise", - "identifier": "enterprise-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v5.2/enterprise-attack/enterprise-attack.json"] - }, - { - "name": "Mobile", - "identifier": "mobile-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v5.2/mobile-attack/mobile-attack.json"] - } - ] - }, - { - "name": "ATT&CK v4", - "version": "4", - "domains": [ - { - "name": "Enterprise", - "identifier": "enterprise-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v4.0/enterprise-attack/enterprise-attack.json"] - }, - { - "name": "Mobile", - "identifier": "mobile-attack", - "data": ["https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v4.0/mobile-attack/mobile-attack.json"] - } - ] - } ], "custom_context_menu_items": [ From 5f2c5e0aac40e0479aee8c1ccbff5d9b0c73cc4a Mon Sep 17 00:00:00 2001 From: Charissa Miller <48832936+clemiller@users.noreply.github.com> Date: Tue, 5 Mar 2024 13:30:57 -0500 Subject: [PATCH 02/39] rename function --- .../tooltip/tooltip.component.spec.ts | 2 +- nav-app/src/app/services/data.service.spec.ts | 12 ++++---- nav-app/src/app/services/data.service.ts | 8 +++--- nav-app/src/app/tabs/tabs.component.spec.ts | 28 +++++++++---------- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/nav-app/src/app/matrix/technique-cell/tooltip/tooltip.component.spec.ts b/nav-app/src/app/matrix/technique-cell/tooltip/tooltip.component.spec.ts index 259ff26fa..38838aa2b 100644 --- a/nav-app/src/app/matrix/technique-cell/tooltip/tooltip.component.spec.ts +++ b/nav-app/src/app/matrix/technique-cell/tooltip/tooltip.component.spec.ts @@ -83,7 +83,7 @@ describe('TooltipComponent', () => { innerWidth: { get: () => 100 }, innerHeight: { get: () => 100 }, }); - component.dataService.setUpURLs(versions); + component.dataService.setUpDomains(versions); component.dataService.domains[0].notes = [new Note(stixSDO)]; component.viewModel = new ViewModel('layer', '33', 'enterprise-attack-13', null); component.viewModel.domainVersionID = 'enterprise-attack-13'; diff --git a/nav-app/src/app/services/data.service.spec.ts b/nav-app/src/app/services/data.service.spec.ts index 84f49e011..f37ab8e64 100755 --- a/nav-app/src/app/services/data.service.spec.ts +++ b/nav-app/src/app/services/data.service.spec.ts @@ -85,7 +85,7 @@ describe('DataService', () => { describe('setup with Workbench integration', () => { beforeEach(() => { configService.versions = MockData.workbenchData; - spyOn(DataService.prototype, 'setUpURLs').and.callThrough(); + spyOn(DataService.prototype, 'setUpDomains').and.callThrough(); mockService = new DataService(http, configService); }); @@ -107,7 +107,7 @@ describe('DataService', () => { describe('setup with TAXII', () => { beforeEach(() => { configService.versions = MockData.taxiiData; - spyOn(DataService.prototype, 'setUpURLs').and.callThrough(); + spyOn(DataService.prototype, 'setUpDomains').and.callThrough(); mockService = new DataService(http, configService); }); @@ -133,7 +133,7 @@ describe('DataService', () => { describe('setup with config data', () => { beforeEach(() => { configService.versions = MockData.configData; - spyOn(DataService.prototype, 'setUpURLs').and.callThrough(); + spyOn(DataService.prototype, 'setUpDomains').and.callThrough(); mockService = new DataService(http, configService); }); @@ -223,7 +223,7 @@ describe('DataService', () => { it('should update domain watchers', () => { let functionSpy = spyOn(dataService, 'getCurrentVersion'); - dataService.setUpURLs(MockData.configData); + dataService.setUpDomains(MockData.configData); let domain = dataService.domains[0]; domain.dataLoadedCallbacks = [dataService.getCurrentVersion]; dataService.parseBundle(domain, MockData.stixBundleSDO); @@ -239,7 +239,7 @@ describe('DataService', () => { domains: MockData.configData[0].domains, }; configService.versions = [MockData.configData[0], newVersion]; - spyOn(DataService.prototype, 'setUpURLs').and.callThrough(); + spyOn(DataService.prototype, 'setUpDomains').and.callThrough(); mockService = new DataService(http, configService); }); @@ -342,7 +342,7 @@ describe('DataService', () => { describe('StixObject tests', () => { beforeEach(() => { configService.versions = MockData.configData; - spyOn(DataService.prototype, 'setUpURLs').and.callThrough(); + spyOn(DataService.prototype, 'setUpDomains').and.callThrough(); mockService = new DataService(http, configService); }); diff --git a/nav-app/src/app/services/data.service.ts b/nav-app/src/app/services/data.service.ts index 98ecb08c2..3f374f853 100755 --- a/nav-app/src/app/services/data.service.ts +++ b/nav-app/src/app/services/data.service.ts @@ -17,7 +17,7 @@ export class DataService { private configService: ConfigService ) { console.debug('initializing data service'); - this.setUpURLs(configService.versions); + this.setUpDomains(configService.versions); } public domain_backwards_compatibility = { @@ -268,11 +268,11 @@ export class DataService { public icsAttackURL: string = 'https://raw.githubusercontent.com/mitre/cti/master/ics-attack/ics-attack.json'; /** - * Set up the URLs for data - * @param {versions} list of versions and domains defined in the configuration file + * Set up the URLs for domains in the list defined in the config file + * @param {versions} list of versions and domains * @memberof DataService */ - public setUpURLs(versions: any[]) { + public setUpDomains(versions: any[]) { versions.forEach((version: any) => { let v: Version = new Version(version['name'], version['version'].match(/\d+/g)[0]); this.versions.push(v); diff --git a/nav-app/src/app/tabs/tabs.component.spec.ts b/nav-app/src/app/tabs/tabs.component.spec.ts index 53a64d71b..7593ed55c 100755 --- a/nav-app/src/app/tabs/tabs.component.spec.ts +++ b/nav-app/src/app/tabs/tabs.component.spec.ts @@ -466,7 +466,7 @@ describe('TabsComponent', () => { })); it('should read and open json file', waitForAsync(() => { - component.dataService.setUpURLs(MockData.configData); + component.dataService.setUpDomains(MockData.configData); let mockedDocElement = document.createElement('input'); mockedDocElement.id = 'uploader'; mockedDocElement.value = 'test1'; @@ -525,7 +525,7 @@ describe('TabsComponent', () => { component.openTab('layer', vm1, true, true, true, true); component.openTab('layer1', vm2, true, true, true, true); expect(component.getScoreExpressionError()).toEqual('Layer b does not match the chosen domain'); - component.dataService.setUpURLs(MockData.configData); // set up data + component.dataService.setUpDomains(MockData.configData); // set up data component.opSettings.domain = 'enterprise-attack-13'; expect(component.getFilteredVMs()).toEqual(component.viewModelsService.viewModels); spyOn(component.dataService, 'loadDomainData').and.returnValue(Promise.resolve()); @@ -539,7 +539,7 @@ describe('TabsComponent', () => { let vm1 = component.viewModelsService.newViewModel('layer', 'enterprise-attack-13'); component.openTab('layer', vm1, true, true, true, true); expect(component.getScoreExpressionError()).toEqual(null); - component.dataService.setUpURLs(MockData.configData); // set up data + component.dataService.setUpDomains(MockData.configData); // set up data component.dataService.parseBundle(component.dataService.getDomain('enterprise-attack-13'), MockData.stixBundleSDO); //load the data component.opSettings.domain = 'enterprise-attack-13'; spyOn(component.dataService, 'loadDomainData').and.returnValue(Promise.resolve()); @@ -555,7 +555,7 @@ describe('TabsComponent', () => { component.openTab('layer', vm1, true, true, true, true); component.openTab('layer2', vm2, true, true, true, true); - component.dataService.setUpURLs(MockData.configDataExtended); // set up data + component.dataService.setUpDomains(MockData.configDataExtended); // set up data component.dataService.parseBundle(component.dataService.getDomain('enterprise-attack-13'), MockData.stixBundleSDO); //load the data component.opSettings.domain = 'enterprise-attack-13'; let alertSpy = spyOn(window, 'alert'); @@ -568,7 +568,7 @@ describe('TabsComponent', () => { describe('versionUpgradeDialog', () => { it('should upgrade layer', waitForAsync(() => { - component.dataService.setUpURLs(MockData.configDataExtended); + component.dataService.setUpDomains(MockData.configDataExtended); let layer = JSON.parse(JSON.stringify(MockLayers.layerFile1)); let vm1 = component.viewModelsService.newViewModel('layer2', 'enterprise-attack-12'); let versionUpgradeSpy = spyOn(component, 'versionUpgradeDialog').and.returnValue( @@ -584,7 +584,7 @@ describe('TabsComponent', () => { })); it('should not upgrade layer', waitForAsync(() => { - component.dataService.setUpURLs(MockData.configDataExtended); + component.dataService.setUpDomains(MockData.configDataExtended); let layer = JSON.parse(JSON.stringify(MockLayers.layerFile1)); let vm1 = component.viewModelsService.newViewModel('layer2', 'enterprise-attack-12'); let versionUpgradeSpy = spyOn(component, 'versionUpgradeDialog').and.returnValue(Promise.resolve(null)); @@ -598,7 +598,7 @@ describe('TabsComponent', () => { })); it('should not upgrade layer with domain data loaded', waitForAsync(() => { - component.dataService.setUpURLs(MockData.configDataExtended); + component.dataService.setUpDomains(MockData.configDataExtended); component.dataService.parseBundle(component.dataService.getDomain('enterprise-attack-13'), MockData.stixBundleSDO); let layer = JSON.parse(JSON.stringify(MockLayers.layerFile1)); let vm1 = component.viewModelsService.newViewModel('layer2', 'enterprise-attack-13'); @@ -623,7 +623,7 @@ describe('TabsComponent', () => { describe('upgradeLayer', () => { it('should upgrade layer', waitForAsync(() => { - component.dataService.setUpURLs(MockData.configDataExtended); + component.dataService.setUpDomains(MockData.configDataExtended); let layer = JSON.parse(JSON.stringify(MockLayers.layerFile1)); let vm1 = component.viewModelsService.newViewModel('layer2', 'enterprise-attack-12'); let versionUpgradeSpy = spyOn(component, 'versionUpgradeDialog').and.returnValue( @@ -639,7 +639,7 @@ describe('TabsComponent', () => { })); it('should not upgrade layer', waitForAsync(() => { - component.dataService.setUpURLs(MockData.configDataExtended); + component.dataService.setUpDomains(MockData.configDataExtended); let layer = JSON.parse(JSON.stringify(MockLayers.layerFile1)); let vm1 = component.viewModelsService.newViewModel('layer2', 'enterprise-attack-12'); let versionUpgradeSpy = spyOn(component, 'versionUpgradeDialog').and.returnValue(Promise.resolve(null)); @@ -653,7 +653,7 @@ describe('TabsComponent', () => { })); it('should not upgrade layer with default layer enabled', waitForAsync(() => { - component.dataService.setUpURLs(MockData.configDataExtended); + component.dataService.setUpDomains(MockData.configDataExtended); let layer = JSON.parse(JSON.stringify(MockLayers.layerFile1)); let vm1 = component.viewModelsService.newViewModel('layer2', 'enterprise-attack-12'); spyOn(component.dataService, 'loadDomainData').and.returnValue(Promise.resolve()); @@ -664,7 +664,7 @@ describe('TabsComponent', () => { })); it('should not upgrade layer with default layer enabled and domain data loaded', waitForAsync(() => { - component.dataService.setUpURLs(MockData.configDataExtended); + component.dataService.setUpDomains(MockData.configDataExtended); component.dataService.parseBundle(component.dataService.getDomain('enterprise-attack-13'), MockData.stixBundleSDO); let bb = JSON.parse(JSON.stringify(MockLayers.layerFile1)); let vm1 = component.viewModelsService.newViewModel('layer2', 'enterprise-attack-13'); @@ -676,7 +676,7 @@ describe('TabsComponent', () => { })); it('should not upgrade layer with domain data loaded', waitForAsync(() => { - component.dataService.setUpURLs(MockData.configDataExtended); + component.dataService.setUpDomains(MockData.configDataExtended); component.dataService.parseBundle(component.dataService.getDomain('enterprise-attack-13'), MockData.stixBundleSDO); let layer = JSON.parse(JSON.stringify(MockLayers.layerFile1)); let vm1 = component.viewModelsService.newViewModel('layer2', 'enterprise-attack-13'); @@ -701,7 +701,7 @@ describe('TabsComponent', () => { describe('loadLayerFromURL', () => { it('should load from url', waitForAsync(() => { - component.dataService.setUpURLs(MockData.configData); + component.dataService.setUpDomains(MockData.configData); component.http = http; spyOn(component.http, 'get').and.returnValue(of(MockLayers.layerFile1)); let versionMismatchSpy = spyOn(component, 'versionMismatchWarning').and.returnValue(Promise.resolve(true)); @@ -728,7 +728,7 @@ describe('TabsComponent', () => { ], }, ]; - component.dataService.setUpURLs(versions); + component.dataService.setUpDomains(versions); component.http = http; spyOn(component.http, 'get').and.returnValue(of(MockLayers.layerFile1)); let versionMismatchSpy = spyOn(component, 'versionMismatchWarning').and.returnValue(Promise.resolve(true)); From a46e40399f98c4a65b79794457cbd065aac76bf7 Mon Sep 17 00:00:00 2001 From: Charissa Miller <48832936+clemiller@users.noreply.github.com> Date: Tue, 5 Mar 2024 13:42:06 -0500 Subject: [PATCH 03/39] move domain class from stix directory --- nav-app/src/app/classes/{stix => }/domain.ts | 24 +++++++++---------- nav-app/src/app/classes/filter.ts | 2 +- nav-app/src/app/classes/index.ts | 1 + nav-app/src/app/classes/stix/index.ts | 1 - nav-app/src/app/services/data.service.spec.ts | 4 ++-- nav-app/src/app/services/data.service.ts | 6 ++--- nav-app/src/app/tabs/tabs.component.spec.ts | 4 ++-- nav-app/src/app/tabs/tabs.component.ts | 3 +-- 8 files changed, 22 insertions(+), 23 deletions(-) rename nav-app/src/app/classes/{stix => }/domain.ts (86%) diff --git a/nav-app/src/app/classes/stix/domain.ts b/nav-app/src/app/classes/domain.ts similarity index 86% rename from nav-app/src/app/classes/stix/domain.ts rename to nav-app/src/app/classes/domain.ts index da91b53f6..49f4d076f 100644 --- a/nav-app/src/app/classes/stix/domain.ts +++ b/nav-app/src/app/classes/domain.ts @@ -1,15 +1,15 @@ -import { ServiceAuth } from '../../services/data.service'; -import { Campaign } from './campaign'; -import { DataComponent } from './data-component'; -import { Group } from './group'; -import { Matrix } from './matrix'; -import { Mitigation } from './mitigation'; -import { Note } from './note'; -import { Software } from './software'; -import { Tactic } from './tactic'; -import { Technique } from './technique'; -import { Version } from '../version'; -import { Asset } from './asset'; +import { ServiceAuth } from '../services/data.service'; +import { Campaign } from './stix/campaign'; +import { DataComponent } from './stix/data-component'; +import { Group } from './stix/group'; +import { Matrix } from './stix/matrix'; +import { Mitigation } from './stix/mitigation'; +import { Note } from './stix/note'; +import { Software } from './stix/software'; +import { Tactic } from './stix/tactic'; +import { Technique } from './stix/technique'; +import { Version } from './version'; +import { Asset } from './stix/asset'; export class Domain { public readonly id: string; // domain ID diff --git a/nav-app/src/app/classes/filter.ts b/nav-app/src/app/classes/filter.ts index 7a665ec9f..b11dc7135 100644 --- a/nav-app/src/app/classes/filter.ts +++ b/nav-app/src/app/classes/filter.ts @@ -1,4 +1,4 @@ -import { Domain } from './stix/domain'; +import { Domain } from './domain'; export class Filter { // the data for a specific filter diff --git a/nav-app/src/app/classes/index.ts b/nav-app/src/app/classes/index.ts index d37f8af3f..80f3cbbab 100644 --- a/nav-app/src/app/classes/index.ts +++ b/nav-app/src/app/classes/index.ts @@ -1,5 +1,6 @@ export { VersionChangelog } from './version-changelog'; export { Version } from './version'; +export { Domain } from './domain'; export { ContextMenuItem } from './context-menu-item'; export { Gradient, Gcolor } from './gradient'; export { Filter } from './filter'; diff --git a/nav-app/src/app/classes/stix/index.ts b/nav-app/src/app/classes/stix/index.ts index 086431d65..4c81a3f22 100644 --- a/nav-app/src/app/classes/stix/index.ts +++ b/nav-app/src/app/classes/stix/index.ts @@ -1,7 +1,6 @@ export { StixObject } from './stix-object'; export { Campaign } from './campaign'; export { DataComponent } from './data-component'; -export { Domain } from './domain'; export { Group } from './group'; export { Matrix } from './matrix'; export { Mitigation } from './mitigation'; diff --git a/nav-app/src/app/services/data.service.spec.ts b/nav-app/src/app/services/data.service.spec.ts index f37ab8e64..aa55302d7 100755 --- a/nav-app/src/app/services/data.service.spec.ts +++ b/nav-app/src/app/services/data.service.spec.ts @@ -1,7 +1,7 @@ import { TestBed } from '@angular/core/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing'; -import { Version, VersionChangelog } from '../classes'; -import { Asset, Campaign, DataComponent, Domain, Group, Matrix, Mitigation, Note, Software, Tactic, Technique } from '../classes/stix'; +import { Domain, Version, VersionChangelog } from '../classes'; +import { Asset, Campaign, DataComponent, Group, Matrix, Mitigation, Note, Software, Tactic, Technique } from '../classes/stix'; import { of } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { Collection } from '../utils/taxii2lib'; diff --git a/nav-app/src/app/services/data.service.ts b/nav-app/src/app/services/data.service.ts index 3f374f853..e60caa2e8 100755 --- a/nav-app/src/app/services/data.service.ts +++ b/nav-app/src/app/services/data.service.ts @@ -3,9 +3,9 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Buffer } from 'buffer'; import { Observable } from 'rxjs/Rx'; import { fromPromise } from 'rxjs/observable/fromPromise'; -import { Asset, Campaign, Domain, DataComponent, Group, Software, Matrix, Technique, Mitigation, Note } from '../classes/stix'; +import { Asset, Campaign, DataComponent, Group, Software, Matrix, Technique, Mitigation, Note } from '../classes/stix'; import { TaxiiConnect, Collection } from '../utils/taxii2lib'; -import { Version, VersionChangelog } from '../classes'; +import { Domain, Version, VersionChangelog } from '../classes'; import { ConfigService } from './config.service'; @Injectable({ @@ -17,7 +17,7 @@ export class DataService { private configService: ConfigService ) { console.debug('initializing data service'); - this.setUpDomains(configService.versions); + this.setUpDomains(configService.versions); } public domain_backwards_compatibility = { diff --git a/nav-app/src/app/tabs/tabs.component.spec.ts b/nav-app/src/app/tabs/tabs.component.spec.ts index 7593ed55c..0df956013 100755 --- a/nav-app/src/app/tabs/tabs.component.spec.ts +++ b/nav-app/src/app/tabs/tabs.component.spec.ts @@ -3,7 +3,7 @@ import { HttpClientTestingModule } from '@angular/common/http/testing'; import { TabsComponent } from './tabs.component'; import { MatDialog, MatDialogModule } from '@angular/material/dialog'; import { DataService } from '../services/data.service'; -import { Tab, TechniqueVM, Version, ViewModel } from '../classes'; +import { Tab, TechniqueVM, Domain, Version, ViewModel } from '../classes'; import { HelpComponent } from '../help/help.component'; import { SvgExportComponent } from '../svg-export/svg-export.component'; import { MatSnackBar } from '@angular/material/snack-bar'; @@ -12,7 +12,7 @@ import { LayerInformationComponent } from '../layer-information/layer-informatio import * as is from 'is_js'; import { HttpClient } from '@angular/common/http'; import { of } from 'rxjs'; -import { Domain, Technique } from '../classes/stix'; +import { Technique } from '../classes/stix'; import { ConfigService } from '../services/config.service'; import * as MockLayers from '../../tests/utils/mock-layers'; import * as MockData from '../../tests/utils/mock-data'; diff --git a/nav-app/src/app/tabs/tabs.component.ts b/nav-app/src/app/tabs/tabs.component.ts index 4877508cb..b223c0991 100755 --- a/nav-app/src/app/tabs/tabs.component.ts +++ b/nav-app/src/app/tabs/tabs.component.ts @@ -1,7 +1,6 @@ import { Component, ViewChild, TemplateRef, AfterViewInit, ViewEncapsulation, Input, Output, EventEmitter } from '@angular/core'; import { DataService } from '../services/data.service'; -import { Domain } from '../classes/stix'; -import { Tab, Version, ViewModel } from '../classes'; +import { Tab, Domain, Version, ViewModel } from '../classes'; import { ConfigService } from '../services/config.service'; import { VersionUpgradeComponent } from '../version-upgrade/version-upgrade.component'; import { HelpComponent } from '../help/help.component'; From 4a8d635b85d4f5ac62cfe597304a8cd647fcd83c Mon Sep 17 00:00:00 2001 From: Charissa Miller <48832936+clemiller@users.noreply.github.com> Date: Tue, 5 Mar 2024 13:48:14 -0500 Subject: [PATCH 04/39] remove unused code --- nav-app/src/app/classes/gradient.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/nav-app/src/app/classes/gradient.ts b/nav-app/src/app/classes/gradient.ts index 074fd4190..4d55d8bf9 100644 --- a/nav-app/src/app/classes/gradient.ts +++ b/nav-app/src/app/classes/gradient.ts @@ -31,7 +31,6 @@ export class Gradient { */ public serialize(): string { let colorList: string[] = []; - let self = this; this.colors.forEach(function (gColor: Gcolor) { let hexstring = tinycolor(gColor.color).toHex8String(); // include the alpha channel colorList.push(hexstring); From cb2366dbe11d04d938094e81bfb6314e33a67da3 Mon Sep 17 00:00:00 2001 From: Charissa Miller <48832936+clemiller@users.noreply.github.com> Date: Tue, 5 Mar 2024 13:52:58 -0500 Subject: [PATCH 05/39] code smell --- nav-app/src/app/services/config.service.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/nav-app/src/app/services/config.service.ts b/nav-app/src/app/services/config.service.ts index 1a5b350bc..372d14db4 100644 --- a/nav-app/src/app/services/config.service.ts +++ b/nav-app/src/app/services/config.service.ts @@ -124,8 +124,10 @@ export class ConfigService { this.features.set(featureObject.name, enabled); return [featureObject.name]; } else { - //has subfeatures - override = override ? override : !featureObject.enabled ? false : null; + // has subfeatures + if (!override) { + override = !featureObject.enabled ? false : null; + } let subfeatures = []; featureObject.subfeatures.forEach(function (subfeature) { subfeatures = Array.prototype.concat(subfeatures, self.setFeature_object(subfeature, override)); @@ -206,6 +208,7 @@ export class ConfigService { }), switchMap((collectionIndexUrl: string) => { if (collectionIndexUrl) return this.http.get(collectionIndexUrl); + // TODO: return properly if no url is provided return of({}); }), map((collectionIndex: any) => { From d968cbbeb15cab18f090d1d2ad4c88a7c4982d06 Mon Sep 17 00:00:00 2001 From: Charissa Miller <48832936+clemiller@users.noreply.github.com> Date: Tue, 5 Mar 2024 14:23:00 -0500 Subject: [PATCH 06/39] parse collection index into domain/version structure --- nav-app/src/app/services/config.service.ts | 2 +- nav-app/src/app/services/data.service.ts | 32 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/nav-app/src/app/services/config.service.ts b/nav-app/src/app/services/config.service.ts index 372d14db4..1dd706da2 100644 --- a/nav-app/src/app/services/config.service.ts +++ b/nav-app/src/app/services/config.service.ts @@ -208,7 +208,7 @@ export class ConfigService { }), switchMap((collectionIndexUrl: string) => { if (collectionIndexUrl) return this.http.get(collectionIndexUrl); - // TODO: return properly if no url is provided + // TODO return properly if no url is provided return of({}); }), map((collectionIndex: any) => { diff --git a/nav-app/src/app/services/data.service.ts b/nav-app/src/app/services/data.service.ts index 12a9ecb65..58ada11c2 100755 --- a/nav-app/src/app/services/data.service.ts +++ b/nav-app/src/app/services/data.service.ts @@ -17,6 +17,13 @@ export class DataService { private configService: ConfigService ) { console.debug('initializing data service'); + if (configService.collectionIndex) { + this.parseCollectionIndex(configService.collectionIndex); + } + // TODO restrict to one or both? + if (configService.versions) { + this.setUpDomains(configService.versions); + } this.setUpDomains(configService.versions); } @@ -313,9 +320,34 @@ export class DataService { this.domains.push(...[enterpriseDomain, mobileDomain, icsDomain]); } + //TODO check this with introduction of collection index this.lowestSupportedVersion = this.versions[this.versions.length - 1]; } + public parseCollectionIndex(collectionIndex: any) { + for (let collection of collectionIndex.collections) { + for (let version of collection.versions) { + let versionNumber = version.version; + let versionName = `${collectionIndex.name} v${versionNumber}`; + let v = this.addVersion(versionName, versionNumber); + this.domains.push(new Domain(collection.id, collection.name, v, [version.url])); + } + } + console.log('**', this.domains, this.versions); + } + + public addVersion(versionName: string, versionNumber: string): Version { + // check if version already exists + let existingVersion = this.versions.find(v => v.name === versionName && v.number === versionNumber); + if (!existingVersion) { + // create and add new version + let version = new Version(versionName, versionNumber); + this.versions.push(version); + return version; + } + return existingVersion; + } + /** * Fetch the domain data from the endpoint */ From a032cc889d9be28e4d41edd9132180977e5e55ab Mon Sep 17 00:00:00 2001 From: Charissa Miller <48832936+clemiller@users.noreply.github.com> Date: Tue, 5 Mar 2024 15:03:22 -0500 Subject: [PATCH 07/39] add mimimum supported version to globals --- nav-app/src/app/tabs/tabs.component.html | 4 ++-- nav-app/src/app/tabs/tabs.component.ts | 11 ++++++----- nav-app/src/app/utils/globals.ts | 1 + 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/nav-app/src/app/tabs/tabs.component.html b/nav-app/src/app/tabs/tabs.component.html index dbe6dd590..467727a67 100755 --- a/nav-app/src/app/tabs/tabs.component.html +++ b/nav-app/src/app/tabs/tabs.component.html @@ -160,7 +160,7 @@