1414SUB_CHARACTERS = ["\\ " , "/" ]
1515
1616
17- def get_stix_data (domain : str , version : str = None , remote : str = None ) -> MemoryStore :
17+ def get_stix_data (domain : str , version : str = None , remote : str = None , stix_file : str = None ) -> MemoryStore :
1818 """Download the ATT&CK STIX data for the given domain and version from MITRE/CTI (or just domain if a remote workbench is specified).
1919
2020 Parameters
@@ -27,36 +27,59 @@ def get_stix_data(domain: str, version: str = None, remote: str = None) -> Memor
2727 remote : str, optional
2828 Optional url to a ATT&CK workbench instance.
2929 If specified, data will be retrieved from the target Workbench instead of MITRE/CTI, by default None
30+ stix_file : str, optional
31+ Path to a local STIX file containing ATT&CK data for a domain, by default None
3032
3133 Returns
3234 -------
3335 MemoryStore
3436 A stix2.MemoryStore object containing the domain data
37+
38+ Raises
39+ ------
40+ ValueError
41+ Raised if both `remote` and `stix_file` are passed
42+ FileNotFoundError
43+ Raised if `stix_file` not found
3544 """
36- if remote : # Using Workbench Instance
37- if ":" not in remote [6 :]:
38- remote += ":3000"
39- if not remote .startswith ("http" ):
40- remote = "http://" + remote
41- url = f"{ remote } /api/stix-bundles?domain={ domain } &includeRevoked=true&includeDeprecated=true"
42- stix_json = requests .get (url ).json ()
43- ms = MemoryStore (stix_json )
44- else : # Using MITRE/CTI
45- if version :
46- url = f"https://raw.githubusercontent.com/mitre/cti/ATT%26CK-{ version } /{ domain } /{ domain } .json"
45+ if remote and stix_file :
46+ raise ValueError ("remote and stix_file are mutually exclusive. Please only use one or the other" )
47+
48+ mem_store = None
49+ if stix_file :
50+ if os .path .exists (stix_file ):
51+ logger .info (f"Loading STIX file from: { stix_file } " )
52+ mem_store = MemoryStore ()
53+ mem_store .load_from_file (stix_file )
4754 else :
48- url = f"https://raw.githubusercontent.com/mitre/cti/master/{ domain } /{ domain } .json"
55+ raise FileNotFoundError (f"{ stix_file } file does not exist." )
56+ else :
57+ if remote :
58+ logger .info ("Downloading ATT&CK data from an ATT&CK Workbench instance" )
59+ if ":" not in remote [6 :]:
60+ remote += ":3000"
61+ if not remote .startswith ("http" ):
62+ remote = "http://" + remote
63+ url = f"{ remote } /api/stix-bundles?domain={ domain } &includeRevoked=true&includeDeprecated=true"
64+ stix_json = requests .get (url ).json ()
65+ mem_store = MemoryStore (stix_json )
66+ else :
67+ logger .info ("Downloading ATT&CK data from github.com/mitre/cti" )
68+ if version :
69+ url = f"https://raw.githubusercontent.com/mitre/cti/ATT%26CK-{ version } /{ domain } /{ domain } .json"
70+ else :
71+ url = f"https://raw.githubusercontent.com/mitre/cti/master/{ domain } /{ domain } .json"
4972
50- stix_json = requests .get (url ).json ()
51- ms = MemoryStore (stix_data = stix_json ["objects" ])
73+ stix_json = requests .get (url ).json ()
74+ mem_store = MemoryStore (stix_data = stix_json ["objects" ])
5275
53- return ms
76+ return mem_store
5477
5578
5679def build_dataframes (src : MemoryStore , domain : str ) -> Dict :
5780 """Build pandas dataframes for each attack type, and return a dictionary lookup for each type to the relevant dataframe.
5881
59- :returns:
82+ :returns:
6083
6184 Parameters
6285 ----------
@@ -247,26 +270,15 @@ def export(
247270 ------
248271 ValueError
249272 Raised if both `remote` and `stix_file` are passed
250- FileNotFoundError
251- Raised if `stix_file` not found
252273 """
253274 if remote and stix_file :
254275 raise ValueError ("remote and stix_file are mutually exclusive. Please only use one or the other" )
255276
256- mem_store = None
257- if remote :
258- mem_store = get_stix_data (domain , version , remote )
259- elif stix_file :
260- if os .path .exists (stix_file ):
261- logger .info (f"Loading STIX file from: { stix_file } " )
262- mem_store = MemoryStore ()
263- mem_store .load_from_file (stix_file )
264- else :
265- raise FileNotFoundError (f"{ stix_file } file does not exist." )
277+ mem_store = get_stix_data (domain = domain , version = version , remote = remote , stix_file = stix_file )
266278
267279 # build dataframes
268280 dataframes = build_dataframes (src = mem_store , domain = domain )
269- write_excel (dataframes , domain , version , outputDir )
281+ write_excel (dataframes = dataframes , domain = domain , version = version , outputDir = outputDir )
270282
271283
272284def main ():
0 commit comments