def _loader(self, data): """ INTERNAL: Acts a middleman for loading values into the technique object from a dict representation :param data: A dict describing the technique :raises UnknownTechniqueProperty: An error indicating that an unexpected property was found on the technique """ for entry in data.keys(): if entry == 'techniqueID': pass elif entry == 'tactic': self.tactic = data[entry] elif entry == 'comment': self.comment = data[entry] elif entry == 'enabled': self.enabled = data[entry] elif entry == 'score': self.score = data[entry] elif entry == 'color': self.color = data[entry] elif entry == 'metadata': self.metadata = data[entry] elif entry == 'showSubtechniques': self.showSubtechniques = data[entry] elif entry == 'links': self.links = data[entry] elif entry == 'aggregateScore': self.aggregateScore = data[entry] else: handler( type(self).__name__, "Unknown technique property: {}".format(entry)) raise UnknownTechniqueProperty
def techniqueID(self, techniqueID): typeChecker(type(self).__name__, techniqueID, str, "techniqueID") if not techniqueID.startswith('T'): handler( type(self).__name__, '{} not a valid value for techniqueID'.format(techniqueID)) raise BadInput else: self.__techniqueID = techniqueID
def gradient(self, gradient): ret = handle_object_placement(self.__gradient, gradient, Gradient) if ret: self.__gradient = ret else: try: loadChecker(type(self).__name__, gradient, ['colors', 'minValue', 'maxValue'], "gradient") self.__gradient = Gradient(gradient['colors'], gradient['minValue'], gradient['maxValue']) except MissingParameters as e: handler(type(self).__name__, 'Gradient {} is missing parameters: ' '{}. Skipping.' .format(gradient, e))
def _build(self): """ Loads the data stored in self.data into a LayerObj (self.layer) """ try: self.__layer = _LayerObj(self._data['name'], self._data['domain']) except BadType or BadInput as e: handler(type(self).__name__, 'Layer is malformed: {}. ' 'Unable to load.'.format(e)) self.__layer = None return except KeyError as e: handler(type(self).__name__, 'Layer is missing parameters: {}. ' 'Unable to load.'.format(e)) self.__layer = None return for key in self._data: if key not in ['name', 'domain']: try: self.__layer._linker(key, self._data[key]) except Exception as e: if self.strict: handler(type(self).__name__, "{} encountered [{}]. " "Unable to load." .format(str(e.__class__.__name__), e)) handler(type(self).__name__, "Full Traceback - {}" .format(traceback.format_exc())) self.__layer = None return
def _linker(self, field, data): """ INTERNAL: Acts as a middleman routing the settings of values within the layer :param field: The value field being set :param data: The corresponding data to set that field to :raises UnknownLayerProperty: An error indicating that an unexpected property was identified """ if field == 'description': self.description = data elif field.startswith('version'): if not field.endswith('s'): # force upgrade print('[Version] - V3 version field detected. Upgrading to V4 Versions object.') ver_obj = dict(layer="4.0", navigator="4.0") self.versions = ver_obj else: self.versions = data elif field == 'filters': self.filters = data elif field == 'sorting': self.sorting = data elif field == 'layout': self.layout = data elif field == 'hideDisabled': self.hideDisabled = data elif field == 'techniques': self.techniques = data elif field == 'gradient': self.gradient = data elif field == 'legendItems': self.legendItems = data elif field == 'showTacticRowBackground': self.showTacticRowBackground = data elif field == 'tacticRowBackground': self.tacticRowBackground = data elif field == 'selectTechniquesAcrossTactics': self.selectTechniquesAcrossTactics = data elif field == 'selectSubtechniquesWithParent': self.selectSubtechniquesWithParent = data elif field == 'metadata': self.metadata = data elif field == 'links': self.links = data else: handler(type(self).__name__, "Unknown layer property: {}" .format(field)) raise UnknownLayerProperty
def links(self, links): typeChecker(type(self).__name__, links, list, "links") if not handle_object_placement(self.__links, links, Link): self.__links = [] entry = "" try: for entry in links: if "divider" in entry: self.__links.append(Link(entry["divider"])) else: self.__links.append(Link(entry['label'], entry['url'])) except KeyError as e: handler(type(self).__name__, 'Link {} is missing parameters: ' '{}. Unable to load.' .format(entry, e))
def versions(self, versions): ret = handle_object_placement(self.__versions, versions, Versions) if ret: self.__versions = ret else: typeChecker(type(self).__name__, versions, dict, "version") attack = UNSETVALUE if 'attack' in versions: attack = versions['attack'] try: loadChecker(type(self).__name__, versions, ['layer', 'navigator'], "versions") self.__versions = Versions(versions['layer'], attack, versions['navigator']) except MissingParameters as e: handler(type(self).__name__, 'versions {} is missing parameters: ' '{}. Skipping.' .format(versions, e))
def legendItems(self, legendItems): typeChecker(type(self).__name__, legendItems, list, "legendItems") self.__legendItems = [] for entry in legendItems: ret = handle_object_placement(self.__legendItems, entry, LegendItem, list=True) if ret: self.__legendItems = ret else: try: loadChecker(type(self).__name__, entry, ['label', 'color'], "legendItem") temp = LegendItem(entry['label'], entry['color']) self.__legendItems.append(temp) except MissingParameters as e: handler(type(self).__name__, 'Legend Item {} is missing parameters: ' '{}. Skipping.' .format(entry, e))
def metadata(self, metadata): typeChecker(type(self).__name__, metadata, list, "metadata") if not handle_object_placement(self.__metadata, metadata, Metadata): self.__metadata = [] entry = "" try: for entry in metadata: if "divider" in entry: self.__metadata.append(MetaDiv(entry["divider"])) else: self.__metadata.append( Metadata(entry['name'], entry['value'])) except KeyError as e: handler( type(self).__name__, 'Metadata {} is missing parameters: ' '{}. Unable to load.'.format(entry, e))
def filters(self, filters): ret = handle_object_placement(self.__filters, filters, Filter) if ret: self.__filters = ret else: temp = Filter(self.domain) try: loadChecker(type(self).__name__, filters, ['platforms'], "filters") # force upgrade to v4 if 'stages' in filters: print('[Filters] - V3 Field "stages" detected. Upgrading Filters object to V4.') temp.platforms = filters['platforms'] self.__filters = temp except MissingParameters as e: handler(type(self).__name__, 'Filters {} is missing parameters: ' '{}. Skipping.' .format(filters, e))
def techniques(self, techniques): typeChecker(type(self).__name__, techniques, list, "techniques") self.__techniques = [] for entry in techniques: ret = handle_object_placement(self.__techniques, entry, Technique, list=True) if ret: self.__techniques = ret else: try: loadChecker(type(self).__name__, entry, ['techniqueID'], "technique") temp = Technique(entry['techniqueID']) temp._loader(entry) self.__techniques.append(temp) except MissingParameters as e: handler(type(self).__name__, 'Technique {} is missing parameters: ' '{}. Skipping.' .format(entry, e))
def metadata(self, metadata): typeChecker(type(self).__name__, metadata, list, "metadata") self.__metadata = [] for entry in metadata: ret = handle_object_placement(self.__metadata, entry, Metadata, list=True) if ret: self.__metadata = ret else: try: if "divider" in entry: self.__metadata.append(MetaDiv(entry["divider"])) else: loadChecker(type(self).__name__, entry, ['name', 'value'], "metadata") self.__metadata.append(Metadata(entry['name'], entry['value'])) except MissingParameters as e: handler( type(self).__name__, 'Metadata {} is missing parameters: {}. Skipping.'.format(entry, e) )
def _aggFunction(self, data_block, total_techs): """ Apply the selected aggregate function to a data_block :param data_block: List containing scores to compute over (generated by compute_aggregate) :param total_techs: Count of number of techniques utilized :return: Calculated score """ if self.showAggregateScores: data = data_block if self.__aggregateFunction == Aggregates.average: if total_techs < len(data_block): handler( type(self).__name__, "Total elements > Expected Length? Defaulting to Total Elements" ) total_techs = len(data_block) return sum(data) / total_techs elif self.__aggregateFunction == Aggregates.min: return min(data) elif self.__aggregateFunction == Aggregates.max: return max(data) elif self.__aggregateFunction == Aggregates.sum: return sum(data)