2017-02-10 22:35:02 +01:00
|
|
|
"""Python APIs for STIX 2."""
|
2017-01-17 21:37:47 +01:00
|
|
|
|
2017-03-22 14:05:59 +01:00
|
|
|
# flake8: noqa
|
|
|
|
|
2017-02-10 22:35:02 +01:00
|
|
|
from .bundle import Bundle
|
2017-05-05 18:32:02 +02:00
|
|
|
from .observables import Artifact, AutonomousSystem, EmailAddress, File
|
2017-04-19 20:32:56 +02:00
|
|
|
from .other import ExternalReference, KillChainPhase, MarkingDefinition, \
|
|
|
|
GranularMarking, StatementMarking, TLPMarking
|
2017-02-24 18:56:55 +01:00
|
|
|
from .sdo import AttackPattern, Campaign, CourseOfAction, Identity, Indicator, \
|
|
|
|
IntrusionSet, Malware, ObservedData, Report, ThreatActor, Tool, \
|
|
|
|
Vulnerability
|
2017-03-31 21:52:27 +02:00
|
|
|
from .sro import Relationship, Sighting
|
2017-04-19 20:32:56 +02:00
|
|
|
from .utils import get_dict
|
2017-04-18 21:19:16 +02:00
|
|
|
from . import exceptions
|
2017-04-05 23:12:44 +02:00
|
|
|
|
|
|
|
|
2017-04-24 22:33:59 +02:00
|
|
|
OBJ_MAP = {
|
|
|
|
'attack-pattern': AttackPattern,
|
|
|
|
'campaign': Campaign,
|
|
|
|
'course-of-action': CourseOfAction,
|
|
|
|
'identity': Identity,
|
|
|
|
'indicator': Indicator,
|
|
|
|
'intrusion-set': IntrusionSet,
|
|
|
|
'malware': Malware,
|
|
|
|
'marking-definition': MarkingDefinition,
|
|
|
|
'observed-data': ObservedData,
|
|
|
|
'report': Report,
|
|
|
|
'relationship': Relationship,
|
|
|
|
'threat-actor': ThreatActor,
|
|
|
|
'tool': Tool,
|
|
|
|
'sighting': Sighting,
|
|
|
|
'vulnerability': Vulnerability,
|
|
|
|
}
|
|
|
|
|
2017-05-03 23:35:33 +02:00
|
|
|
OBJ_MAP_OBSERVABLE = {
|
|
|
|
'artifact': Artifact,
|
2017-05-04 00:19:30 +02:00
|
|
|
'autonomous-system': AutonomousSystem,
|
2017-05-05 18:32:02 +02:00
|
|
|
'email-address': EmailAddress,
|
2017-05-03 23:35:33 +02:00
|
|
|
'file': File,
|
|
|
|
}
|
|
|
|
|
2017-04-24 22:33:59 +02:00
|
|
|
|
2017-05-05 18:32:02 +02:00
|
|
|
def parse(data):
|
2017-04-05 23:12:44 +02:00
|
|
|
"""Deserialize a string or file-like object into a STIX object"""
|
|
|
|
|
2017-04-19 20:32:56 +02:00
|
|
|
obj = get_dict(data)
|
2017-04-05 23:12:44 +02:00
|
|
|
|
|
|
|
if 'type' not in obj:
|
|
|
|
# TODO parse external references, kill chain phases, and granular markings
|
|
|
|
pass
|
2017-04-19 15:22:08 +02:00
|
|
|
else:
|
|
|
|
try:
|
2017-05-05 18:32:02 +02:00
|
|
|
obj_class = OBJ_MAP[obj['type']]
|
2017-04-19 15:22:08 +02:00
|
|
|
except KeyError:
|
|
|
|
# TODO handle custom objects
|
2017-05-03 23:35:33 +02:00
|
|
|
raise ValueError("Can't parse unknown object type '%s'!" % obj['type'])
|
|
|
|
return obj_class(**obj)
|
2017-04-05 23:12:44 +02:00
|
|
|
|
|
|
|
return obj
|
2017-05-05 18:32:02 +02:00
|
|
|
|
|
|
|
|
|
|
|
def parse_observable(data, _valid_refs):
|
|
|
|
"""Deserialize a string or file-like object into a STIX Cyber Observable
|
|
|
|
object.
|
|
|
|
"""
|
|
|
|
|
|
|
|
obj = get_dict(data)
|
|
|
|
obj['_valid_refs'] = _valid_refs
|
|
|
|
|
|
|
|
if 'type' not in obj:
|
|
|
|
raise ValueError("'type' is a required field!")
|
|
|
|
try:
|
|
|
|
obj_class = OBJ_MAP_OBSERVABLE[obj['type']]
|
|
|
|
except KeyError:
|
|
|
|
# TODO handle custom objects
|
|
|
|
raise ValueError("Can't parse unknown object type '%s'!" % obj['type'])
|
|
|
|
return obj_class(**obj)
|