@@ -15,6 +15,7 @@ def __init__(self, url, username, password):
1515 self .jirahandler = jirahandler
1616
1717 def get_attack_techniques (self ):
18+ # Deprecated, keeping just in case
1819
1920 try :
2021 print ("[*] Obtaining ATT&CK's techniques..." )
@@ -87,7 +88,89 @@ def create_attack_techniques(self, key):
8788
8889 print ("[*] Done!" )
8990
91+ def create_attack_techniques_and_subtechniques (self , key ):
9092
93+ # this creates each sub-technique as a SubTask
94+ # no issue links are created
95+
96+ jiraclient = self .jirahandler
97+ techniques = self .get_attack_techniques ()
98+ sorted_techniques = sorted (techniques , key = lambda k : k ['external_references' ][0 ]['external_id' ])
99+
100+ print ("[*] Creating Jira issues for ATT&CK's techniques..." )
101+
102+ for technique in sorted_techniques :
103+ try :
104+ custom_fields = self .jirahandler .get_custom_fields ()
105+
106+ name = technique ['name' ]
107+ id = technique ['external_references' ][0 ]['external_id' ]
108+ url = technique ['external_references' ][0 ]['url' ]
109+ tactic = technique ['kill_chain_phases' ][0 ]['phase_name' ]
110+ description = technique ['description' ]
111+
112+ # some techniques dont have the field populated
113+ if 'x_mitre_data_sources' in technique .keys ():
114+ datasources = technique ['x_mitre_data_sources' ]
115+ else :
116+ datasources = []
117+
118+ ds_payload = []
119+ for ds in datasources : ds_payload .append ({'value' :ds .title ()})
120+
121+ if not technique ['x_mitre_is_subtechnique' ]:
122+ # Not a sub-technique
123+ issue_dict = {
124+ "fields" : {
125+ "project" : {"key" : key },
126+ #"summary": name + " (" + id + ")",
127+ "summary" : name ,
128+ "description" : description ,
129+ "issuetype" : {"name" : "Task" },
130+ custom_fields ['Id' ]: id ,
131+ custom_fields ['Tactic' ]: {'value' : tactic },
132+ custom_fields ['Maturity' ]: {'value' : 'Not Tracked' },
133+ custom_fields ['Url' ]: url ,
134+ custom_fields ['Datasources' ]: ds_payload ,
135+ # "customfield_11050": "Value that we're putting into a Free Text Field."
136+ }
137+ }
138+ #print("Creating Technique")
139+ parent_id = jiraclient .create_issue (issue_dict , id )
140+ #print (parent_id)
141+ #print("Created Technique with id : "+ str(parent_id))
142+
143+ else :
144+ # Sub-technique
145+ issue_dict = {
146+ "fields" : {
147+ "parent" : {"id" : parent_id ['id' ]},
148+ "project" : {"key" : key },
149+ #"summary": name + " (" + id + ")",
150+ "summary" : name ,
151+ "description" : description ,
152+ "issuetype" : {"name" : "Sub-task" },
153+ custom_fields ['Id' ]: id ,
154+ custom_fields ['Tactic' ]: {'value' : tactic },
155+ custom_fields ['Maturity' ]: {'value' : 'Not Tracked' },
156+ custom_fields ['Url' ]: url ,
157+ custom_fields ['Datasources' ]: ds_payload ,
158+ custom_fields ['Sub-Technique of' ]: jiraclient .url + "/browse/" + parent_id ['key' ],
159+ }
160+ }
161+ #print("Creating sub Technique under parent " + str(parent_id))
162+ ret_id = jiraclient .create_issue (issue_dict , id )
163+ #print("Created sub Technique with id : "+ str(ret_id))
164+
165+ except Exception as ex :
166+ print ("\t [*] Could not create ticket for " + id )
167+ print (ex )
168+ traceback .print_exc (file = sys .stdout )
169+ pass
170+ # print(ex)
171+ # sys.exit()
172+
173+ print ("[*] Done!" )
91174
92175 def generate_json_layer (self , hideDisabled ):
93176 VERSION = "2.2"
@@ -151,9 +234,9 @@ def set_up_jira_automated(self, project, key):
151234 self .jirahandler .create_project (project , key )
152235 self .jirahandler .create_custom_fields ()
153236 self .jirahandler .add_custom_field_options ()
154- self .jirahandler .add_custom_field_to_screen_tab (key )
237+ self .jirahandler .add_custom_fields_to_screen (key )
155238 self .jirahandler .hide_unwanted_fields (key )
156- self .create_attack_techniques (key )
239+ self .create_attack_techniques_and_subtechniques (key )
157240
158241
159242def main ():
0 commit comments