Skip to content
This repository was archived by the owner on Dec 11, 2023. It is now read-only.

Commit 3d60dc6

Browse files
author
clittle
committed
Patch to matrix_gen to fix revoked status issue, minor patches to
spacing/alignment
1 parent af4fedb commit 3d60dc6

3 files changed

Lines changed: 63 additions & 33 deletions

File tree

layers/exporters/matrix_gen.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,20 @@ def __init__(self, source='taxii', local=None):
109109
self.matrix = {}
110110
self._build_matrix()
111111

112+
@staticmethod
113+
def _remove_revoked_deprecated(content):
114+
"""Remove any revoked or deprecated objects from queries made to the data source"""
115+
return list(
116+
filter(
117+
lambda x: x.get("x_mitre_deprecated", False) is False and x.get("revoked", False) is False,
118+
content
119+
)
120+
)
121+
122+
def _search(self, domain, query):
123+
interum = self.collections[domain].query(query)
124+
return self._remove_revoked_deprecated(interum)
125+
112126
def _get_tactic_listing(self, domain='enterprise'):
113127
"""
114128
INTERNAL - retrieves tactics for the associated domain
@@ -117,11 +131,11 @@ def _get_tactic_listing(self, domain='enterprise'):
117131
"""
118132
tactics = {}
119133
t_filt = []
120-
matrix = self.collections[domain].query([Filter('type', '=', 'x-mitre-matrix')])
134+
matrix = self._search(domain, [Filter('type', '=', 'x-mitre-matrix')])
121135
for i in range(len(matrix)):
122136
tactics[matrix[i]['name']] = []
123137
for tactic_id in matrix[i]['tactic_refs']:
124-
tactics[matrix[i]['name']].append(self.collections[domain].query([Filter('id', '=', tactic_id)])[0])
138+
tactics[matrix[i]['name']].append(self._search(domain,([Filter('id', '=', tactic_id)]))[0])
125139
for entry in tactics[matrix[0]['name']]:
126140
self.convert_data[entry['x_mitre_shortname']] = entry['name']
127141
self.convert_data[entry['name']] = entry['x_mitre_shortname']
@@ -137,7 +151,8 @@ def _get_technique_listing(self, tactic, domain='enterprise'):
137151
"""
138152
techniques = []
139153
subtechs = {}
140-
techs = self.collections[domain].query([Filter('type', '=', 'attack-pattern'), Filter('kill_chain_phases.phase_name', '=', tactic)])
154+
techs = self._search(domain,[Filter('type', '=', 'attack-pattern'),
155+
Filter('kill_chain_phases.phase_name', '=', tactic)])
141156
for entry in techs:
142157
if entry['kill_chain_phases'][0]['kill_chain_name'] == 'mitre-attack' or \
143158
entry['kill_chain_phases'][0]['kill_chain_name'] == 'mitre-mobile-attack':

layers/exporters/svg_objects.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ def _optimalFontSize(st, width, height, maxFontSize=12):
135135
num_breaks = 2
136136
elif num_spaces < 50:
137137
num_breaks = 3
138+
139+
if _findSpace([st], width, height, maxFontSize) == maxFontSize:
140+
return maxFontSize, [st]
138141
breaks = _find_breaks(num_spaces, num_breaks)
139142
for binaryString in breaks:
140143
wordSet = []
@@ -152,8 +155,8 @@ def _optimalFontSize(st, width, height, maxFontSize=12):
152155
if size > bestSize:
153156
bestSize = size
154157
bestWordArrangement = wordSet
155-
if size == maxFontSize:
156-
break
158+
#if size == maxFontSize:
159+
# break
157160

158161
return bestSize, bestWordArrangement
159162

@@ -257,24 +260,28 @@ def build(height, width, label, config, variant='text', t1text=None, t2text=None
257260
upper = G(tx=0, ty=2.1)
258261
internal.append(upper)
259262
if t1text is not None:
260-
fs, patch_text = _optimalFontSize(t1text, width, (height-5)/2, maxFontSize=28)
263+
bu = t2text is not None and t2text is not ""
264+
theight = (height-5)
265+
if bu:
266+
theight = theight / 2
267+
fs, patch_text = _optimalFontSize(t1text, width, theight, maxFontSize=28)
261268
lines = len(patch_text)
262-
y = (height-5)/4 + 2.1
269+
y = theight/2 + 2.1
263270
if lines > 1:
264-
y = y - (((height-5)/16) * (lines-1))
271+
y = y - (theight / 5 * (lines-1))
265272
t1 = Text("\n".join(patch_text), fs, '', x=4, y=y)
266273
upper.append(t1)
267-
upper.append(Line(0, width-10, (height-5)/2, (height-5)/2, stroke='#dddddd'))
268-
if t2text is not None and t2text is not "":
274+
if bu:
275+
upper.append(Line(0, width - 10, theight, theight, stroke='#dddddd'))
269276
upper_fs = fs
270-
lower_offset = ((height-5)/2 + 2.1)
277+
lower_offset = (theight + 2.1)
271278
lower = G(tx=0, ty= lower_offset)
272279
fs, patch_text = _optimalFontSize(t2text, width, (height - (height/3 + upper_fs)), maxFontSize=28)
273-
y = (height-5)/4 + 2.1
280+
y = theight / 2 + 2.1
274281
lines = len(patch_text)
275282
adju = "\n".join(patch_text)
276283
if lines > 1:
277-
y = y - (((height - 5) / 16) * (lines - 1))
284+
y = y - ((theight / 5) * (lines - 1))
278285
if float(fs) > lower_offset:
279286
y = y + 2*(float(fs) - lower_offset)
280287
t2 = Text(adju, fs, '', x=4, y=y)

layers/exporters/svg_templates.py

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ def _build_headers(self, name, config, desc=None, filters=None, gradient=None):
6060
psych = 0
6161
overlay = None
6262
if config.showHeader:
63-
operation_x = max_x - 30
6463

6564
root = G(tx=5, ty=5, style='font-family: {}'.format(ff))
6665

@@ -74,11 +73,12 @@ def _build_headers(self, name, config, desc=None, filters=None, gradient=None):
7473
header_count += 1
7574
if config.showFilters:
7675
header_count += 1
77-
if config.showLegend and config.legendDocked:
76+
if config.showLegend and gradient is not False and config.legendDocked:
7877
header_count += 1
7978

79+
operation_x = (max_x - 10) - (15 * (header_count - 1))
8080
if header_count > 0:
81-
header_width = max_x / header_count - (15 * (header_count-1))
81+
header_width = operation_x / header_count
8282
if config.showAbout:
8383
if desc is not None:
8484
g = SVG_HeaderBlock().build(height=header_height, width=header_width, label='about', t1text=name,
@@ -96,11 +96,11 @@ def _build_headers(self, name, config, desc=None, filters=None, gradient=None):
9696
fi.stages = ["act"]
9797
g2 = SVG_HeaderBlock().build(height=header_height, width=header_width, label='filters',
9898
t1text=', '.join(fi.platforms), t2text=fi.stages[0], config=config)
99-
b2 = G(tx=operation_x / header_count * psych + 20 * psych)
99+
b2 = G(tx=operation_x / header_count * psych + 15 * psych)
100100
header.append(b2)
101101
b2.append(g2)
102102
psych += 1
103-
if config.showLegend:
103+
if config.showLegend and gradient is not False:
104104
gr = gradient
105105
if gr is None:
106106
gr = Gradient(colors=["#ff6666","#ffe766","#8ec843"], minValue=1, maxValue=100)
@@ -111,7 +111,7 @@ def _build_headers(self, name, config, desc=None, filters=None, gradient=None):
111111
(gr.compute_color(int(gr.minValue + div * i)), gr.minValue + div * i))
112112
colors.append((gr.compute_color(gr.maxValue), gr.maxValue))
113113
if config.legendDocked:
114-
b3 = G(tx=operation_x / header_count * psych + 20 * psych)
114+
b3 = G(tx=operation_x / header_count * psych + 15 * psych)
115115
g3 = SVG_HeaderBlock().build(height=header_height, width=header_width, label='legend',
116116
variant='graphic', colors=colors, config=config)
117117
header.append(b3)
@@ -149,7 +149,7 @@ def get_tactic(self, tactic, height, width, config, colors=[], scores=[], subtec
149149
:param subtechs: List of visible subtechniques
150150
:param exclude: List of excluded techniques
151151
:param mode: Tuple describing text for techniques (Show Name, Show ID)
152-
:return: Instantiated tactic column
152+
:return: Instantiated tactic column (or none if no techniques were found)
153153
"""
154154
offset = 0
155155
column = G(ty=2)
@@ -172,6 +172,8 @@ def get_tactic(self, tactic, height, width, config, colors=[], scores=[], subtec
172172
a, offset = self.get_tech(offset, mode, x, tactic=self.h.convert(tactic.tactic.name),
173173
subtechniques=[], colors=colors, config=config, height=height, width=width)
174174
column.append(a)
175+
if len(column.children) == 0:
176+
return None
175177
return column
176178

177179
def get_tech(self, offset, mode, technique, tactic, config, height, width, subtechniques=[], colors=[]):
@@ -209,30 +211,33 @@ def export(self, showName, showID, lhandle, config, sort=0, scores=[], colors=[]
209211
:param exclude: List of excluded techniques
210212
:return:
211213
"""
214+
grad = False
215+
if len(scores):
216+
grad = lhandle.gradient
212217
d, presence, overlay = self._build_headers(lhandle.name, config, lhandle.description, lhandle.filters,
213-
lhandle.gradient)
218+
grad)
214219
self.codex = self.h._adjust_ordering(self.codex, sort, scores)
215220
self.lhandle = lhandle
216221
glob = G()
217222
index = 5
218223
lengths = []
219224
for x in self.codex:
220-
sum = len(x.techniques)
225+
su = len(x.techniques)
221226
for enum in exclude:
222227
if enum[0] in [y.id for y in x.techniques]:
223228
if self.h.convert(enum[1]) == x.tactic.name or enum[1] == False:
224-
sum -= 1
229+
su -= 1
225230
for y in x.subtechniques:
226231
if y in [z[0] for z in subtechs]:
227-
sum += len(x.subtechniques[y])
228-
lengths.append(sum)
229-
tech_width = (convertToPx(config.width, config.unit) / len(self.codex)) - 10
232+
su += len(x.subtechniques[y])
233+
lengths.append(su)
234+
tech_width = (convertToPx(config.width, config.unit) / sum([1 for x in lengths if x > 0])) - 10
230235
header_offset = convertToPx(config.headerHeight, config.unit)
231236
if presence == 0:
232237
header_offset = 0
233-
header_offset += 30
238+
header_offset += 15
234239
tech_height = (convertToPx(config.height, config.unit) - header_offset -
235-
convertToPx(config.border, config.unit)) / max(lengths)
240+
convertToPx(config.border, config.unit)) / (max(lengths) + 1)
236241
incre = tech_width + 10
237242
for x in self.codex:
238243
disp = ''
@@ -245,16 +250,19 @@ def export(self, showName, showID, lhandle, config, sort=0, scores=[], colors=[]
245250

246251
g = G(tx=index, ty=header_offset)
247252

248-
index += incre
249-
fs, _ = _optimalFontSize(disp, tech_width, tech_height+10, maxFontSize=28)
253+
fs, _ = _optimalFontSize(disp, tech_width, tech_height, maxFontSize=28)
250254
tx = Text(ctype='TacticName', font_size=fs, text=disp, position='middle')
251-
gt = G(tx=(tech_width)/2)
255+
gt = G(tx=(tech_width)/2, ty=(tech_height)/2)
252256
gt.append(tx)
253257
a = self.get_tactic(x, tech_height, tech_width, colors=colors, subtechs=subtechs, exclude=exclude,
254258
mode=(showName, showID), scores=scores, config=config)
259+
b = G(ty=tech_height)
255260
g.append(gt)
256-
g.append(a)
257-
glob.append(g)
261+
b.append(a)
262+
g.append(b)
263+
if a:
264+
glob.append(g)
265+
index += incre
258266
d.append(glob)
259267
if overlay:
260268
d.append(overlay)

0 commit comments

Comments
 (0)