def test_add_lmco_phase(self): phase = lmco.PHASE_DELIVERY refs = KillChainPhasesReference() refs.append(phase) self.assertTrue(isinstance(refs[0], KillChainPhaseReference)) self.assertTrue(refs[0].phase_id, lmco.PHASE_DELIVERY.phase_id)
def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): super(Indicator, self).__init__(id_=id_, idref=idref, timestamp=timestamp, title=title, description=description, short_description=short_description) self.observable = None self.indicator_types = IndicatorTypes() self.test_mechanisms = TestMechanisms() self.alternative_id = None self.suggested_coas = SuggestedCOAs() self.sightings = Sightings() self.composite_indicator_expression = None self.kill_chain_phases = KillChainPhasesReference() self.related_indicators = RelatedIndicators() self.related_campaigns = RelatedCampaignRefs() self.observable_composition_operator = "OR" self.related_packages = RelatedPackageRefs()
def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): super(Indicator, self).__init__(id_=id_, idref=idref, timestamp=timestamp, title=title, description=description, short_description=short_description) self.producer = None self.observables = None self.indicator_types = IndicatorTypes() self.confidence = None self.indicated_ttps = _IndicatedTTPs() self.test_mechanisms = TestMechanisms() self.alternative_id = None self.suggested_coas = SuggestedCOAs() self.sightings = Sightings() self.composite_indicator_expression = None self.handling = None self.kill_chain_phases = KillChainPhasesReference() self.valid_time_positions = _ValidTimePositions() self.related_indicators = None self.related_campaigns = RelatedCampaignRefs() self.observable_composition_operator = "OR" self.likely_impact = None self.negate = None self.related_packages = RelatedPackageRefs()
def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): self.id_ = id_ or stix.utils.create_id("indicator") self.idref = idref self.version = self._version self.producer = None self.observables = None self.title = title self.description = description self.short_description = short_description self.indicator_types = None self.confidence = None self.indicated_ttps = None self.test_mechanisms = None self.alternative_id = None self.suggested_coas = SuggestedCOAs() self.sightings = Sightings() self.composite_indicator_expression = None self.handling = None self.kill_chain_phases = KillChainPhasesReference() self.valid_time_positions = None self.related_indicators = None self.observable_composition_operator = "AND" self.likely_impact = None if timestamp: self.timestamp = timestamp else: self.timestamp = datetime.now(tzutc()) if not idref else None
def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): self.id_ = id_ or stix.utils.create_id("indicator") self.idref = idref self.version = self._version self.producer = None self.observables = None self.title = title self.description = description self.short_description = short_description self.indicator_types = None self.confidence = None self.indicated_ttps = None self.test_mechanisms = None self.alternative_id = None self.suggested_coas = SuggestedCOAs() self.sightings = Sightings() self.composite_indicator_expression = None self.handling = None self.kill_chain_phases = KillChainPhasesReference() self.valid_time_positions = None self.related_indicators = None self.observable_composition_operator = "AND" if timestamp: self.timestamp = timestamp else: self.timestamp = datetime.now(tzutc()) if not idref else None
def generate_indicators(self, count): '''Generate a list of STIX Indicators''' indicators = [] for i in range(0, count): indicator = Indicator(title='Multiple indicator types') indicator.set_producer_identity(Identity(name='Secret Source')) indicator.set_produced_time(datetime.today()) indicator.add_indicator_type(choice(['Malware Artifacts', 'C2', 'Exfiltration'])) indicator.add_short_description('Short description...') indicator.add_description('Long description...') indicator.confidence = Confidence(choice(['High', 'Medium', 'Low', 'None', 'Unknown'])) kill_chain_phase = choice(LMCO_KILL_CHAIN_PHASES) indicator.kill_chain_phases = KillChainPhasesReference( [KillChainPhaseReference(name=kill_chain_phase.name)]) ips = self.gen_ips(randint(0, 5)) for ip in ips: indicator.add_observable(ip) # user_agents = self.gen_user_agents(randint(0, 5)) # for ua in user_agents: # indicator.add_observable(ua) # fqnds = self.gen_fqdns(randint(0, 5)) # for f in fqnds: # indicator.add_observable(f) # urls = self.gen_urls(randint(0, 5)) # for u in urls: # indicator.add_observable(u) indicators.append(indicator) return indicators
def from_dict(cls, dict_repr, return_obj=None): if not dict_repr: return None if not return_obj: return_obj = cls() super(Indicator, cls).from_dict(dict_repr, return_obj=return_obj) get = dict_repr.get return_obj.negate = get('negate') return_obj.alternative_id = get('alternative_id') return_obj.indicated_ttps = _IndicatedTTPs.from_dict(get('indicated_ttps')) return_obj.test_mechanisms = TestMechanisms.from_list(get('test_mechanisms')) return_obj.suggested_coas = SuggestedCOAs.from_dict(get('suggested_coas')) return_obj.sightings = Sightings.from_dict(get('sightings')) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_dict(get('composite_indicator_expression')) return_obj.kill_chain_phases = KillChainPhasesReference.from_dict(get('kill_chain_phases')) return_obj.related_indicators = RelatedIndicators.from_dict(get('related_indicators')) return_obj.likely_impact = Statement.from_dict(get('likely_impact')) return_obj.indicator_types = IndicatorTypes.from_list(get('indicator_types')) return_obj.confidence = Confidence.from_dict(get('confidence')) return_obj.valid_time_positions = _ValidTimePositions.from_dict(get('valid_time_positions')) return_obj.observable = Observable.from_dict(get('observable')) return_obj.producer = InformationSource.from_dict(get('producer')) return_obj.related_campaigns = RelatedCampaignRefs.from_dict(get('related_campaigns')) return_obj.related_packages = RelatedPackageRefs.from_dict(get('related_packages')) return return_obj
def from_obj(cls, obj, return_obj=None): if not obj: return None if not return_obj: return_obj = cls() super(Indicator, cls).from_obj(obj, return_obj=return_obj) if isinstance(obj, cls._binding_class): return_obj.negate = obj.negate return_obj.producer = InformationSource.from_obj(obj.Producer) return_obj.confidence = Confidence.from_obj(obj.Confidence) return_obj.sightings = Sightings.from_obj(obj.Sightings) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_obj(obj.Composite_Indicator_Expression) return_obj.kill_chain_phases = KillChainPhasesReference.from_obj(obj.Kill_Chain_Phases) return_obj.related_indicators = RelatedIndicators.from_obj(obj.Related_Indicators) return_obj.likely_impact = Statement.from_obj(obj.Likely_Impact) return_obj.indicator_types = IndicatorTypes.from_obj(obj.Type) return_obj.test_mechanisms = TestMechanisms.from_obj(obj.Test_Mechanisms) return_obj.suggested_coas = SuggestedCOAs.from_obj(obj.Suggested_COAs) return_obj.alternative_id = obj.Alternative_ID return_obj.indicated_ttps = _IndicatedTTPs.from_obj(obj.Indicated_TTP) return_obj.valid_time_positions = _ValidTimePositions.from_obj(obj.Valid_Time_Position) return_obj.observable = Observable.from_obj(obj.Observable) return_obj.related_campaigns = RelatedCampaignRefs.from_obj(obj.Related_Campaigns) return_obj.related_packages = RelatedPackageRefs.from_obj(obj.Related_Packages) return return_obj
def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): super(Indicator, self).__init__( id_=id_, idref=idref, timestamp=timestamp, title=title, description=description, short_description=short_description ) self.producer = None self.observables = None self.indicator_types = IndicatorTypes() self.confidence = None self.indicated_ttps = _IndicatedTTPs() self.test_mechanisms = TestMechanisms() self.alternative_id = None self.suggested_coas = SuggestedCOAs() self.sightings = Sightings() self.composite_indicator_expression = None self.kill_chain_phases = KillChainPhasesReference() self.valid_time_positions = _ValidTimePositions() self.related_indicators = None self.related_campaigns = RelatedCampaignRefs() self.observable_composition_operator = "OR" self.likely_impact = None self.negate = None self.related_packages = RelatedPackageRefs()
def add_kill_chain_phase_reference_data_from_frame(api_object, frame): indicator = api_object.obj indicator_builder_data = frame[0].f_locals['indicator_data'] kill_chain_phase_id = indicator_builder_data.get('kill_chain_phase') if kill_chain_phase_id: kill_chain_phase = KillChainPhaseReference( kill_chain_id=KILL_CHAIN_ID, phase_id=kill_chain_phase_id) indicator._object.kill_chain_phases = KillChainPhasesReference( [kill_chain_phase]) return api_object
def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): super(TTP, self).__init__(id_=id_, idref=idref, timestamp=timestamp, title=title, description=description, short_description=short_description) self.related_packages = RelatedPackageRefs() self.exploit_targets = ExploitTargets() self.related_ttps = RelatedTTPs() self.kill_chain_phases = KillChainPhasesReference()
def from_dict(cls, dict_repr, return_obj=None): if not dict_repr: return None if not return_obj: return_obj = cls() return_obj.id_ = dict_repr.get('id') return_obj.idref = dict_repr.get('idref') return_obj.timestamp = dict_repr.get('timestamp') return_obj.title = dict_repr.get('title') return_obj.version = dict_repr.get('version', cls._version) observable_dict = dict_repr.get('observable') producer_dict = dict_repr.get('producer') description_dict = dict_repr.get('description') indicator_type_list = dict_repr.get('indicator_types', []) confidence_dict = dict_repr.get('confidence') alternative_id_dict = dict_repr.get('alternative_id') valid_time_position_dict = dict_repr.get('valid_time_positions') return_obj.short_description = StructuredText.from_dict(dict_repr.get('short_description')) return_obj.indicated_ttps = [RelatedTTP.from_dict(x) for x in dict_repr.get('indicated_ttps', [])] return_obj.test_mechanisms = [_BaseTestMechanism.from_dict(x) for x in dict_repr.get('test_mechanisms', [])] return_obj.suggested_coas = SuggestedCOAs.from_dict(dict_repr.get('suggested_coas')) return_obj.sightings = Sightings.from_dict(dict_repr.get('sightings')) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_dict(dict_repr.get('composite_indicator_expression')) return_obj.handling = Marking.from_dict(dict_repr.get('handling')) return_obj.kill_chain_phases = KillChainPhasesReference.from_dict(dict_repr.get('kill_chain_phases')) return_obj.related_indicators = RelatedIndicators.from_dict(dict_repr.get('related_indicators')) return_obj.likely_impact = Statement.from_dict(dict_repr.get('likely_impact')) if observable_dict: return_obj.add_observable(Observable.from_dict(observable_dict)) if producer_dict: return_obj.producer = InformationSource.from_dict(producer_dict) if description_dict: return_obj.description = StructuredText.from_dict(description_dict) for indicator_type_dict in indicator_type_list: return_obj.add_indicator_type(VocabString.from_dict(indicator_type_dict)) if confidence_dict: return_obj.confidence = Confidence.from_dict(confidence_dict) if alternative_id_dict: return_obj.alternative_id = alternative_id_dict if valid_time_position_dict: for valid_time_position_type_dict in valid_time_position_dict: return_obj.add_valid_time_position(ValidTime.from_dict(valid_time_position_type_dict)) return return_obj
def from_obj(cls, obj, return_obj=None): if not obj: return None if not return_obj: return_obj = cls() return_obj.id_ = obj.get_id() return_obj.idref = obj.get_idref() return_obj.timestamp = obj.get_timestamp() if isinstance(obj, cls._binding_class): return_obj.title = obj.get_Title() return_obj.description = StructuredText.from_obj(obj.get_Description()) return_obj.short_description = StructuredText.from_obj(obj.get_Short_Description()) return_obj.producer = InformationSource.from_obj(obj.get_Producer()) return_obj.confidence = Confidence.from_obj(obj.get_Confidence()) return_obj.sightings = Sightings.from_obj(obj.get_Sightings()) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_obj(obj.get_Composite_Indicator_Expression()) return_obj.handling = Marking.from_obj(obj.get_Handling()) return_obj.kill_chain_phases = KillChainPhasesReference.from_obj(obj.get_Kill_Chain_Phases()) return_obj.related_indicators = RelatedIndicators.from_obj(obj.get_Related_Indicators()) return_obj.likely_impact = Statement.from_obj(obj.get_Likely_Impact()) if obj.get_version(): return_obj.version = obj.get_version() if obj.get_Type(): for indicator_type in obj.get_Type(): return_obj.add_indicator_type(VocabString.from_obj(indicator_type)) if obj.get_Observable(): observable_obj = obj.get_Observable() observable = Observable.from_obj(observable_obj) return_obj.observables.append(observable) if obj.get_Indicated_TTP(): return_obj.indicated_ttps = [RelatedTTP.from_obj(x) for x in obj.get_Indicated_TTP()] if obj.get_Test_Mechanisms(): return_obj.test_mechanisms = [_BaseTestMechanism.from_obj(x) for x in obj.get_Test_Mechanisms().get_Test_Mechanism()] if obj.get_Suggested_COAs(): return_obj.suggested_coas = SuggestedCOAs.from_obj(obj.get_Suggested_COAs()) if obj.get_Alternative_ID(): return_obj.alternative_id = obj.get_Alternative_ID() if obj.get_Valid_Time_Position(): return_obj.valid_time_positions = [ValidTime.from_obj(x) for x in obj.get_Valid_Time_Position()] return return_obj
def from_obj(cls, obj, return_obj=None): if not obj: return None if not return_obj: return_obj = cls() super(TTP, cls).from_obj(obj, return_obj=return_obj) if isinstance(obj, cls._binding_class): return_obj.behavior = Behavior.from_obj(obj.Behavior) return_obj.related_ttps = RelatedTTPs.from_obj(obj.Related_TTPs) return_obj.exploit_targets = ExploitTargets.from_obj(obj.Exploit_Targets) return_obj.resources = Resource.from_obj(obj.Resources) return_obj.victim_targeting = VictimTargeting.from_obj(obj.Victim_Targeting) return_obj.intended_effects = _IntendedEffects.from_obj(obj.Intended_Effect) return_obj.kill_chain_phases = KillChainPhasesReference.from_obj(obj.Kill_Chain_Phases) return_obj.related_packages = RelatedPackageRefs.from_obj(obj.Related_Packages) return return_obj
def from_dict(cls, dict_repr, return_obj=None): if not dict_repr: return None if not return_obj: return_obj = cls() super(TTP, cls).from_dict(dict_repr, return_obj=return_obj) get = dict_repr.get return_obj.behavior = Behavior.from_dict(get('behavior')) return_obj.related_ttps = RelatedTTPs.from_dict(get('related_ttps')) return_obj.exploit_targets = ExploitTargets.from_dict(get('exploit_targets')) return_obj.intended_effects = _IntendedEffects.from_dict(get('intended_effects')) return_obj.resources = Resource.from_dict(get('resources')) return_obj.victim_targeting = VictimTargeting.from_dict(get('victim_targeting')) return_obj.related_packages = RelatedPackageRefs.from_dict(get('related_packages')) return_obj.kill_chain_phases = KillChainPhasesReference.from_dict(get('kill_chain_phases')) return return_obj
def from_dict(cls, dict_repr, return_obj=None): if not dict_repr: return None if not return_obj: return_obj = cls() super(Indicator, cls).from_dict(dict_repr, return_obj=return_obj) get = dict_repr.get return_obj.negate = get('negate') return_obj.alternative_id = get('alternative_id') return_obj.indicated_ttps = _IndicatedTTPs.from_dict( get('indicated_ttps')) return_obj.test_mechanisms = TestMechanisms.from_list( get('test_mechanisms')) return_obj.suggested_coas = SuggestedCOAs.from_dict( get('suggested_coas')) return_obj.sightings = Sightings.from_dict(get('sightings')) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_dict( get('composite_indicator_expression')) return_obj.handling = Marking.from_dict(get('handling')) return_obj.kill_chain_phases = KillChainPhasesReference.from_dict( get('kill_chain_phases')) return_obj.related_indicators = RelatedIndicators.from_dict( get('related_indicators')) return_obj.likely_impact = Statement.from_dict(get('likely_impact')) return_obj.indicator_types = IndicatorTypes.from_list( get('indicator_types')) return_obj.confidence = Confidence.from_dict(get('confidence')) return_obj.valid_time_positions = _ValidTimePositions.from_dict( get('valid_time_positions')) return_obj.observable = Observable.from_dict(get('observable')) return_obj.producer = InformationSource.from_dict(get('producer')) return_obj.related_campaigns = RelatedCampaignRefs.from_dict( get('related_campaigns')) return_obj.related_packages = RelatedPackageRefs.from_dict( get('related_packages')) return return_obj
def from_obj(cls, obj, return_obj=None): if not obj: return None if not return_obj: return_obj = cls() super(Indicator, cls).from_obj(obj, return_obj=return_obj) if isinstance(obj, cls._binding_class): return_obj.negate = obj.negate return_obj.producer = InformationSource.from_obj(obj.Producer) return_obj.confidence = Confidence.from_obj(obj.Confidence) return_obj.sightings = Sightings.from_obj(obj.Sightings) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_obj( obj.Composite_Indicator_Expression) return_obj.handling = Marking.from_obj(obj.Handling) return_obj.kill_chain_phases = KillChainPhasesReference.from_obj( obj.Kill_Chain_Phases) return_obj.related_indicators = RelatedIndicators.from_obj( obj.Related_Indicators) return_obj.likely_impact = Statement.from_obj(obj.Likely_Impact) return_obj.indicator_types = IndicatorTypes.from_obj(obj.Type) return_obj.test_mechanisms = TestMechanisms.from_obj( obj.Test_Mechanisms) return_obj.suggested_coas = SuggestedCOAs.from_obj( obj.Suggested_COAs) return_obj.alternative_id = obj.Alternative_ID return_obj.indicated_ttps = _IndicatedTTPs.from_obj( obj.Indicated_TTP) return_obj.valid_time_positions = _ValidTimePositions.from_obj( obj.Valid_Time_Position) return_obj.observable = Observable.from_obj(obj.Observable) return_obj.related_campaigns = RelatedCampaignRefs.from_obj( obj.Related_Campaigns) return_obj.related_packages = RelatedPackageRefs.from_obj( obj.Related_Packages) return return_obj
def main(): stix_pkg = STIXPackage() # create LM-style kill chain # REF: http://stix.mitre.org/language/version{{site.current_version}}/stix_v{{site.current_version}}_lmco_killchain.xml recon = KillChainPhase(phase_id="stix:TTP-af1016d6-a744-4ed7-ac91-00fe2272185a", name="Reconnaissance", ordinality="1") weapon = KillChainPhase(phase_id="stix:TTP-445b4827-3cca-42bd-8421-f2e947133c16", name="Weaponization", ordinality="2") deliver = KillChainPhase(phase_id="stix:TTP-79a0e041-9d5f-49bb-ada4-8322622b162d", name="Delivery", ordinality="3") exploit = KillChainPhase(phase_id="stix:TTP-f706e4e7-53d8-44ef-967f-81535c9db7d0", name="Exploitation", ordinality="4") install = KillChainPhase(phase_id="stix:TTP-e1e4e3f7-be3b-4b39-b80a-a593cfd99a4f", name="Installation", ordinality="5") control = KillChainPhase(phase_id="stix:TTP-d6dc32b9-2538-4951-8733-3cb9ef1daae2", name="Command and Control", ordinality="6") action = KillChainPhase(phase_id="stix:TTP-786ca8f9-2d9a-4213-b38e-399af4a2e5d6", name="Actions on Objectives", ordinality="7") lmchain = KillChain(id_="stix:TTP-af3e707f-2fb9-49e5-8c37-14026ca0a5ff", name="LM Cyber Kill Chain") lmchain.definer = "LMCO" lmchain.kill_chain_phases = [recon, weapon, deliver, exploit, install, control, action] stix_pkg.ttps.kill_chains.append(lmchain) infect = KillChainPhase(name="Infect Machine") exfil = KillChainPhase(name="Exfiltrate Data") mychain = KillChain(name="Organization-specific Kill Chain") mychain.definer = "Myself" mychain.kill_chain_phases = [infect, exfil] stix_pkg.ttps.add_ttp(TTP()) stix_pkg.ttps.kill_chains.append(mychain) indicator = Indicator() indicator.kill_chain_phases = KillChainPhasesReference([ KillChainPhaseReference(phase_id=exfil.phase_id, kill_chain_id=mychain.id_), KillChainPhaseReference(phase_id=action.phase_id, kill_chain_id=lmchain.id_) ]) stix_pkg.add_indicator(indicator) print(stix_pkg.to_xml(encoding=None))
def process_kill_chain_phases(phases, obj1x): for phase in phases: if phase["kill_chain_name"] in _KILL_CHAINS: kill_chain_phases = _KILL_CHAINS[ phase["kill_chain_name"]]["phases"] if not phase["phase_name"] in kill_chain_phases: kill_chain_phases.update({ phase["phase_name"]: KillChainPhase(phase_id=create_id1x("TTP"), name=phase["phase_name"], ordinality=None) }) _KILL_CHAINS[phase["kill_chain_name"]][ "kill_chain"].add_kill_chain_phase( kill_chain_phases[phase["phase_name"]]) kcp = kill_chain_phases[phase["phase_name"]] if not obj1x.kill_chain_phases: obj1x.kill_chain_phases = KillChainPhasesReference() else: kc = KillChain(id_=create_id1x("TTP"), name=phase["kill_chain_name"]) _KILL_CHAINS[phase["kill_chain_name"]] = {"kill_chain": kc} kcp = KillChainPhase(name=phase["phase_name"], phase_id=create_id1x("TTP")) kc.add_kill_chain_phase(kcp) _KILL_CHAINS[phase["kill_chain_name"]]["phases"] = { phase["phase_name"]: kcp } obj1x.add_kill_chain_phase( KillChainPhaseReference( phase_id=kcp.phase_id, name=kcp.name, ordinality=None, kill_chain_id=_KILL_CHAINS[ phase["kill_chain_name"]]["kill_chain"].id_, kill_chain_name=_KILL_CHAINS[ phase["kill_chain_name"]]["kill_chain"].name))
def kill_chain_phases(self, value): self._kill_chain_phases = KillChainPhasesReference(value)
class TTP(stix.BaseCoreComponent): """Implementation of the STIX TTP. Args: id_ (optional): An identifier. If ``None``, a value will be generated via ``mixbox.idgen.create_id()``. If set, this will unset the ``idref`` property. idref (optional): An identifier reference. If set this will unset the ``id_`` property. timestamp (optional): A timestamp value. Can be an instance of ``datetime.datetime`` or ``str``. description: A description of the purpose or intent of this object. short_description: A short description of the intent or purpose of this object. title: The title of this object. """ _binding = ttp_binding _binding_class = _binding.TTPType _namespace = "http://stix.mitre.org/TTP-1" _version = "1.2" _ALL_VERSIONS = ("1.0", "1.0.1", "1.1", "1.1.1", "1.2") _ID_PREFIX = "ttp" behavior = fields.TypedField("Behavior", Behavior) related_ttps = fields.TypedField("Related_TTPs", RelatedTTPs) intended_effects = StatementField("Intended_Effect", Statement, vocab_type=vocabs.IntendedEffect, multiple=True) resources = fields.TypedField("Resources", Resource) victim_targeting = fields.TypedField("Victim_Targeting", VictimTargeting) exploit_targets = fields.TypedField("Exploit_Targets", ExploitTargets) related_packages = fields.TypedField("Related_Packages", RelatedPackageRefs) kill_chain_phases = fields.TypedField("Kill_Chain_Phases", KillChainPhasesReference) information_source = fields.TypedField("Information_Source", InformationSource) def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): super(TTP, self).__init__(id_=id_, idref=idref, timestamp=timestamp, title=title, description=description, short_description=short_description) self.related_packages = RelatedPackageRefs() self.exploit_targets = ExploitTargets() self.related_ttps = RelatedTTPs() self.kill_chain_phases = KillChainPhasesReference() def add_related_ttp(self, value): """Adds an Related TTP to the :attr:`related_ttps` list property of this :class:`TTP`. The `TTP` parameter must be an instance of :class:`.RelatedTTP` or :class:`TTP`. If the `TTP` parameter is ``None``, no item wil be added to the ``related_ttps`` list property. Calling this method is the same as calling ``append()`` on the ``related_ttps`` property. See Also: The :class:`RelatedTTPs` documentation. Note: If the `TTP` parameter is not an instance of :class:`.RelatedTTP` an attempt will be made to convert it to one. Args: TTP: An instance of :class:`TTP` or :class:`.RelatedTTP`. Raises: ValueError: If the `TTP` parameter cannot be converted into an instance of :class:`.RelatedTTP` """ self.related_ttps.append(value) def add_exploit_target(self, value): """Adds a :class:`.ExploitTarget` object to the :attr:`exploit_targets` collection. """ self.exploit_targets.append(value) def add_intended_effect(self, value): """Adds a :class:`.Statement` object to the :attr:`intended_effects` collection. If `value` is a string, an attempt will be made to convert it into an instance of :class:`.Statement`. """ self.intended_effects.append(value) def add_kill_chain_phase(self, value): """Adds a :class:`.KillChainPhaseReference` to the :attr:`kill_chain_phases` collection. Args: value: A :class:`.KillChainPhase`, :class:`.KillChainPhaseReference` or a ``str`` representing the phase_id of. Note that you if you are defining a custom Kill Chain, you need to add it to the STIX package separately. """ self.kill_chain_phases.append(value) def add_related_package(self, value): """Adds a :class:`.RelatedPackageRef` object to the :attr:`related_packages` collection. Args: value: A :class:`.RelatedPackageRef` or a :class:`.STIXPackage` object. """ self.related_packages.append(value)
class Indicator(stix.BaseCoreComponent): """Implementation of the STIX Indicator. Args: id_ (optional): An identifier. If ``None``, a value will be generated via ``mixbox.idgen.create_id()``. If set, this will unset the ``idref`` property. idref (optional): An identifier reference. If set this will unset the ``id_`` property. title (optional): A string title. timestamp (optional): A timestamp value. Can be an instance of ``datetime.datetime`` or ``str``. description (optional): A string description. short_description (optional): A string short description. """ _binding = indicator_binding _binding_class = indicator_binding.IndicatorType _namespace = 'http://stix.mitre.org/Indicator-2' _version = "2.2" _ALL_VERSIONS = ("2.0", "2.0.1", "2.1", "2.1.1", "2.2") _ALLOWED_COMPOSITION_OPERATORS = ('AND', 'OR') _ID_PREFIX = "indicator" def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): super(Indicator, self).__init__( id_=id_, idref=idref, timestamp=timestamp, title=title, description=description, short_description=short_description ) self.producer = None self.observables = None self.indicator_types = IndicatorTypes() self.confidence = None self.indicated_ttps = _IndicatedTTPs() self.test_mechanisms = TestMechanisms() self.alternative_id = None self.suggested_coas = SuggestedCOAs() self.sightings = Sightings() self.composite_indicator_expression = None self.kill_chain_phases = KillChainPhasesReference() self.valid_time_positions = _ValidTimePositions() self.related_indicators = None self.related_campaigns = RelatedCampaignRefs() self.observable_composition_operator = "OR" self.likely_impact = None self.negate = None self.related_packages = RelatedPackageRefs() @property def producer(self): """Contains information about the source of the :class:`Indicator`. Default Value: ``None`` Returns: An instance of :class:`stix.common.information_source.InformationSource` Raises: ValueError: If set to a value that is not ``None`` and not an instance of :class:`stix.common.information_source.InformationSource` """ return self._producer @producer.setter def producer(self, value): self._set_var(InformationSource, try_cast=False, producer=value) @property def observable(self): """A convenience property for accessing or setting the only ``cybox.core.Observable`` instance held by this Indicator. Default Value: Empty ``list``. Setting this property results in the ``observables`` property being reinitialized to an empty ``list`` and appending the input value, resulting in a ``list`` containing one value. Note: If the ``observables`` list contains more than one item, this property will only return the first item in the list. Returns: An instance of ``cybox.core.Observable``. Raises: ValueError: If set to a value that cannot be converted to an instance of ``cybox.core.Observable``. """ if self.observables: return self.observables[0] else: return None @observable.setter def observable(self, observable): self._observables = _Observables(observable) @property def observables(self): """A list of ``cybox.core.Observable`` instances. This can be set to a single object instance or a list of objects. Note: If the input value or values are not instance(s) of ``cybox.core.Observable``, an attempt will be made to convert the value to an instance of ``cybox.core.Observable``. Default Value: Empty ``list`` Returns: A ``list`` of ``cybox.core.Observable`` instances. Raises: ValueError: If set to a value that cannot be converted to an instance of ``cybox.core.Observable``. """ return self._observables @observables.setter def observables(self, value): self._observables = _Observables(value) def add_observable(self, observable): """Adds an observable to the ``observables`` list property of the :class:`Indicator`. If the `observable` parameter is ``None``, no item will be added to the ``observables`` list. Note: The STIX Language dictates that an :class:`Indicator` can have only one ``Observable`` under it. Because of this, the ``to_xml()`` method will convert the ``observables`` list into an ``cybox.core.ObservableComposition`` instance, in which each item in the ``observables`` list will be added to the composition. By default, the ``operator`` of the composition layer will be set to ``"OR"``. The ``operator`` value can be changed via the ``observable_composition_operator`` property. Args: observable: An instance of ``cybox.core.Observable`` or an object type that can be converted into one. Raises: ValueError: If the `observable` param cannot be converted into an instance of ``cybox.core.Observable``. """ self.observables.append(observable) @property def alternative_id(self): """An alternative identifi er for this :class:`Indicator` This property can be set to a single string identifier or a list of identifiers. If set to a single object, the object will be inserted into an empty list internally. Default Value: Empty ``list`` Returns: A list of alternative ids. """ return self._alternative_id @alternative_id.setter def alternative_id(self, value): self._alternative_id = [] if not value: return elif utils.is_sequence(value): self._alternative_id.extend(x for x in value if x) else: self._alternative_id.append(value) def add_alternative_id(self, value): """Adds an alternative id to the ``alternative_id`` list property. Note: If ``None`` is passed in no value is added to the ``alternative_id`` list property. Args: value: An identifier value. """ if not value: return self.alternative_id.append(value) @property def valid_time_positions(self): """A list of valid time positions for this :class:`Indicator`. This property can be set to a single instance or a list of :class:`stix.indicator.valid_time.ValidTime` instances. If set to a single instance, that object is converted into a list containing one item. Default Value: Empty ``list`` Returns: A list of :class:`stix.indicator.valid_time.ValidTime` instances. """ return self._valid_time_positions @valid_time_positions.setter def valid_time_positions(self, value): self._valid_time_positions = _ValidTimePositions(value) def add_valid_time_position(self, value): """Adds an valid time position to the ``valid_time_positions`` property list. If `value` is ``None``, no item is added to the ``value_time_positions`` list. Args: value: An instance of :class:`stix.indicator.valid_time.ValidTime`. Raises: ValueError: If the `value` argument is not an instance of :class:`stix.indicator.valid_time.ValidTime`. """ self.valid_time_positions.append(value) @property def indicator_types(self): """A list of indicator types for this :class:`Indicator`. This property can be set to lists or single instances of ``str`` or :class:`stix.common.vocabs.VocabString` or an instance of :class:`IndicatorTypes`. Note: If an instance of ``str`` is passed in (or a ``list`` containing ``str`` values) an attempt will be made to convert that string value to an instance of :class:`stix.common.vocabs.IndicatorType`. Default Value: An empty ``IndicatorTypes`` instance. See Also: Documentation for :class:`IndicatorTypes`. Returns: An instance of ``IndicatorTypes``. """ return self._indicator_types @indicator_types.setter def indicator_types(self, value): self._indicator_types = IndicatorTypes(value) def add_indicator_type(self, value): """Adds a value to the ``indicator_types`` list property. The `value` parameter can be a ``str`` or an instance of :class:`stix.common.vocabs.VocabString`. Note: If the `value` parameter is a ``str`` instance, an attempt will be made to convert it into an instance of :class:`stix.common.vocabs.IndicatorType` Args: value: An instance of :class:`stix.common.vocabs.VocabString` or ``str``. Raises: ValueError: If the `value` param is a ``str`` instance that cannot be converted into an instance of :class:`stix.common.vocabs.IndicatorType`. """ self.indicator_types.append(value) @property def confidence(self): """The confidence for this :class:`Indicator`. This property can be set to an instance of ``str``, :class:`stix.common.vocabs.VocabString`, or :class:`stix.common.confidence.Confidence`. Default Value: ``None`` Note: If set to an instance of ``str`` or :class:`stix.common.vocabs.VocabString`, that value will be wrapped in an instance of :class:`stix.common.confidence.Confidence`. Returns: An instance of of :class:`stix.common.confidence.Confidence`. Raises: ValueError: If set to a ``str`` value that cannot be converted into an instance of :class:`stix.common.confidence.Confidence`. """ return self._confidence @confidence.setter def confidence(self, value): self._set_var(Confidence, confidence=value) @property def indicated_ttps(self): return self._indicated_ttps @indicated_ttps.setter def indicated_ttps(self, value): self._indicated_ttps = _IndicatedTTPs(value) def add_indicated_ttp(self, v): """Adds an Indicated TTP to the ``indicated_ttps`` list property of this :class:`Indicator`. The `v` parameter must be an instance of :class:`stix.common.related.RelatedTTP` or :class:`stix.ttp.TTP`. If the `v` parameter is ``None``, no item wil be added to the ``indicated_ttps`` list property. Note: If the `v` parameter is not an instance of :class:`stix.common.related.RelatedTTP` an attempt will be made to convert it to one. Args: v: An instance of :class:`stix.common.related.RelatedTTP` or :class:`stix.ttp.TTP`. Raises: ValueError: If the `v` parameter cannot be converted into an instance of :class:`stix.common.related.RelatedTTP` """ self.indicated_ttps.append(v) @property def test_mechanisms(self): return self._test_mechanisms @test_mechanisms.setter def test_mechanisms(self, value): self._test_mechanisms = TestMechanisms(value) def add_test_mechanism(self, tm): """Adds an Test Mechanism to the ``test_mechanisms`` list property of this :class:`Indicator`. The `tm` parameter must be an instance of a :class:`stix.indicator.test_mechanism._BaseTestMechanism` implementation. If the `tm` parameter is ``None``, no item will be added to the ``test_mechanisms`` list property. See Also: Test Mechanism implementations are found under the :mod:`stix.extensions.test_mechanism` package. Args: tm: An instance of a :class:`stix.indicator.test_mechanism._BaseTestMechanism` implementation. Raises: ValueError: If the `tm` parameter is not an instance of :class:`stix.indicator.test_mechanism._BaseTestMechanism` """ self.test_mechanisms.append(tm) @property def related_indicators(self): return self._related_indicators @related_indicators.setter def related_indicators(self, value): if isinstance(value, RelatedIndicators): self._related_indicators = value else: self._related_indicators = RelatedIndicators(value) def add_related_indicator(self, indicator): """Adds an Related Indicator to the ``related_indicators`` list property of this :class:`Indicator`. The `indicator` parameter must be an instance of :class:`stix.common.related.RelatedIndicator` or :class:`Indicator`. If the `indicator` parameter is ``None``, no item wil be added to the ``related_indicators`` list property. Calling this method is the same as calling ``append()`` on the ``related_indicators`` proeprty. See Also: The :class:`RelatedIndicators` documentation. Note: If the `tm` parameter is not an instance of :class:`stix.common.related.RelatedIndicator` an attempt will be made to convert it to one. Args: indicator: An instance of :class:`Indicator` or :class:`stix.common.related.RelatedIndicator`. Raises: ValueError: If the `indicator` parameter cannot be converted into an instance of :class:`stix.common.related.RelatedIndicator` """ self.related_indicators.append(indicator) @property def related_campaigns(self): return self._related_campaigns @related_campaigns.setter def related_campaigns(self, value): if isinstance(value, RelatedCampaignRefs): self._related_campaigns = value else: self._related_campaigns = RelatedCampaignRefs(value) def add_related_campaign(self, value): """Adds a Related Campaign to this Indicator. The `value` parameter must be an instance of :class:`.RelatedCampaignRef` or :class:`.CampaignRef`. If the `value` parameter is ``None``, no item wil be added to the ``related_campaigns`` collection. Calling this method is the same as calling ``append()`` on the ``related_campaigns`` property. See Also: The :class:`.RelatedCampaignRef` documentation. Note: If the `value` parameter is not an instance of :class:`.RelatedCampaignRef` an attempt will be made to convert it to one. Args: value: An instance of :class:`.RelatedCampaignRef` or :class:`.Campaign`. Raises: ValueError: If the `value` parameter cannot be converted into an instance of :class:`.RelatedCampaignRef` """ self.related_campaigns.append(value) @property def observable_composition_operator(self): return self._observable_composition_operator @observable_composition_operator.setter def observable_composition_operator(self, value): if value in self._ALLOWED_COMPOSITION_OPERATORS: self._observable_composition_operator = value return error = "observable_composition_operator must one of {0}" error = error.format(self._ALLOWED_COMPOSITION_OPERATORS) raise ValueError(error) @property def likely_impact(self): return self._likely_impact @likely_impact.setter def likely_impact(self, value): self._set_var(Statement, likely_impact=value) @property def negate(self): return self._negate @negate.setter def negate(self, value): self._negate = utils.xml_bool(value) @property def kill_chain_phases(self): return self._kill_chain_phases @kill_chain_phases.setter def kill_chain_phases(self, value): self._kill_chain_phases = KillChainPhasesReference(value) def add_kill_chain_phase(self, value): """Add a new Kill Chain Phase reference to this Indicator. Args: value: a :class:`stix.common.kill_chains.KillChainPhase` or a `str` representing the phase_id of. Note that you if you are defining a custom Kill Chain, you need to add it to the STIX package separately. """ self.kill_chain_phases.append(value) @property def related_packages(self): return self._related_packages @related_packages.setter def related_packages(self, value): self._related_packages = RelatedPackageRefs(value) def add_related_package(self, value): self.related_packages.append(value) def set_producer_identity(self, identity): """Sets the name of the producer of this indicator. This is the same as calling ``indicator.producer.identity.name = identity``. If the ``producer`` property is ``None``, it will be initialized to an instance of :class:`stix.common.information_source.InformationSource`. If the ``identity`` property of the ``producer`` instance is ``None``, it will be initialized to an instance of :class:`stix.common.identity.Identity`. Note: if the `identity` parameter is not an instance :class:`stix.common.identity.Identity` an attempt will be made to convert it to one. Args: identity: An instance of ``str`` or ``stix.common.identity.Identity``. """ def unset_producer_identity(): try: self.producer.identity.name = None except AttributeError: pass if not identity: unset_producer_identity() return if not self.producer: self.producer = InformationSource() if isinstance(identity, Identity): self.producer.identity = identity return if not self.producer.identity: self.producer.identity = Identity() self.producer.identity.name = str(identity) def set_produced_time(self, produced_time): """Sets the ``produced_time`` property of the ``producer`` property instance fo `produced_time`. This is the same as calling ``indicator.producer.time.produced_time = produced_time``. The `produced_time` parameter must be an instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Note: If `produced_time` is a ``str`` or ``datetime.datetime`` instance an attempt will be made to convert it into an instance of ``cybox.common.DateTimeWithPrecision``. Args: produced_time: An instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. """ if not self.producer: self.producer = InformationSource() if not self.producer.time: self.producer.time = Time() self.producer.time.produced_time = produced_time def get_produced_time(self): """Gets the produced time for this :class:`Indicator`. This is the same as calling ``produced_time = indicator.producer.time.produced_time``. Returns: ``None`` or an instance of ``cybox.common.DateTimeWithPrecision``. """ try: return self.producer.time.produced_time except AttributeError: return None def set_received_time(self, received_time): """Sets the received time for this :class:`Indicator`. This is the same as calling ``indicator.producer.time.produced_time = produced_time``. The `received_time` parameter must be an instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Args: received_time: An instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Note: If `received_time` is a ``str`` or ``datetime.datetime`` instance an attempt will be made to convert it into an instance of ``cybox.common.DateTimeWithPrecision``. """ if not self.producer: self.producer = InformationSource() if not self.producer.time: self.producer.time = Time() self.producer.time.received_time = received_time def get_received_time(self): """Gets the received time for this :class:`Indicator`. This is the same as calling ``received_time = indicator.producer.time.received_time``. Returns: ``None`` or an instance of ``cybox.common.DateTimeWithPrecision``. """ try: return self.producer.time.received_time except AttributeError: return None def _merge_observables(self, observables): observable_composition = ObservableComposition() observable_composition.operator = self.observable_composition_operator for observable in observables: observable_composition.add(observable) root_observable = Observable() root_observable.observable_composition = observable_composition return root_observable def add_object(self, object_): """Adds a python-cybox Object instance to the ``observables`` list property. This is the same as calling ``indicator.add_observable(object_)``. Note: If the `object` param is not an instance of ``cybox.core.Object`` an attempt will be made to to convert it into one before wrapping it in an ``cybox.core.Observable`` layer. Args: object_: An instance of ``cybox.core.Object`` or an object that can be converted into an instance of ``cybox.core.Observable`` Raises: ValueError: if the `object_` param cannot be converted to an instance of ``cybox.core.Observable``. """ if not object_: return observable = Observable(object_) self.add_observable(observable) def to_obj(self, return_obj=None, ns_info=None): if not return_obj: return_obj = self._binding_class() super(Indicator, self).to_obj(return_obj=return_obj, ns_info=ns_info) return_obj.negate = True if self.negate else None if self.confidence: return_obj.Confidence = self.confidence.to_obj(ns_info=ns_info) if self.indicator_types: return_obj.Type = self.indicator_types.to_obj(ns_info=ns_info) if self.indicated_ttps: return_obj.Indicated_TTP = self.indicated_ttps.to_obj(ns_info=ns_info) if self.producer: return_obj.Producer = self.producer.to_obj(ns_info=ns_info) if self.test_mechanisms: return_obj.Test_Mechanisms = self.test_mechanisms.to_obj(ns_info=ns_info) if self.likely_impact: return_obj.Likely_Impact = self.likely_impact.to_obj(ns_info=ns_info) if self.alternative_id: return_obj.Alternative_ID = self.alternative_id if self.valid_time_positions: return_obj.Valid_Time_Position = self.valid_time_positions.to_obj(ns_info=ns_info) if self.suggested_coas: return_obj.Suggested_COAs = self.suggested_coas.to_obj(ns_info=ns_info) if self.sightings: return_obj.Sightings = self.sightings.to_obj(ns_info=ns_info) if self.composite_indicator_expression: return_obj.Composite_Indicator_Expression = self.composite_indicator_expression.to_obj(ns_info=ns_info) if self.kill_chain_phases: return_obj.Kill_Chain_Phases = self.kill_chain_phases.to_obj(ns_info=ns_info) if self.related_indicators: return_obj.Related_Indicators = self.related_indicators.to_obj(ns_info=ns_info) if self.related_campaigns: return_obj.Related_Campaigns = self.related_campaigns.to_obj(ns_info=ns_info) if self.related_packages: return_obj.Related_Packages = self.related_packages.to_obj(ns_info=ns_info) if self.observables: if len(self.observables) > 1: root_observable = self._merge_observables(self.observables) else: root_observable = self.observables[0] return_obj.Observable = root_observable.to_obj(ns_info=ns_info) return return_obj @classmethod def from_obj(cls, obj, return_obj=None): if not obj: return None if not return_obj: return_obj = cls() super(Indicator, cls).from_obj(obj, return_obj=return_obj) if isinstance(obj, cls._binding_class): return_obj.negate = obj.negate return_obj.producer = InformationSource.from_obj(obj.Producer) return_obj.confidence = Confidence.from_obj(obj.Confidence) return_obj.sightings = Sightings.from_obj(obj.Sightings) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_obj(obj.Composite_Indicator_Expression) return_obj.kill_chain_phases = KillChainPhasesReference.from_obj(obj.Kill_Chain_Phases) return_obj.related_indicators = RelatedIndicators.from_obj(obj.Related_Indicators) return_obj.likely_impact = Statement.from_obj(obj.Likely_Impact) return_obj.indicator_types = IndicatorTypes.from_obj(obj.Type) return_obj.test_mechanisms = TestMechanisms.from_obj(obj.Test_Mechanisms) return_obj.suggested_coas = SuggestedCOAs.from_obj(obj.Suggested_COAs) return_obj.alternative_id = obj.Alternative_ID return_obj.indicated_ttps = _IndicatedTTPs.from_obj(obj.Indicated_TTP) return_obj.valid_time_positions = _ValidTimePositions.from_obj(obj.Valid_Time_Position) return_obj.observable = Observable.from_obj(obj.Observable) return_obj.related_campaigns = RelatedCampaignRefs.from_obj(obj.Related_Campaigns) return_obj.related_packages = RelatedPackageRefs.from_obj(obj.Related_Packages) return return_obj def to_dict(self): keys = ('observables', 'observable_composition_operator', 'negate') d = utils.to_dict(self, skip=keys) if self.negate: d['negate'] = True if self.observables: if len(self.observables) == 1: d['observable'] = self.observables[0].to_dict() else: composite_observable = self._merge_observables(self.observables) d['observable'] = composite_observable.to_dict() return d @classmethod def from_dict(cls, dict_repr, return_obj=None): if not dict_repr: return None if not return_obj: return_obj = cls() super(Indicator, cls).from_dict(dict_repr, return_obj=return_obj) get = dict_repr.get return_obj.negate = get('negate') return_obj.alternative_id = get('alternative_id') return_obj.indicated_ttps = _IndicatedTTPs.from_dict(get('indicated_ttps')) return_obj.test_mechanisms = TestMechanisms.from_list(get('test_mechanisms')) return_obj.suggested_coas = SuggestedCOAs.from_dict(get('suggested_coas')) return_obj.sightings = Sightings.from_dict(get('sightings')) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_dict(get('composite_indicator_expression')) return_obj.kill_chain_phases = KillChainPhasesReference.from_dict(get('kill_chain_phases')) return_obj.related_indicators = RelatedIndicators.from_dict(get('related_indicators')) return_obj.likely_impact = Statement.from_dict(get('likely_impact')) return_obj.indicator_types = IndicatorTypes.from_list(get('indicator_types')) return_obj.confidence = Confidence.from_dict(get('confidence')) return_obj.valid_time_positions = _ValidTimePositions.from_dict(get('valid_time_positions')) return_obj.observable = Observable.from_dict(get('observable')) return_obj.producer = InformationSource.from_dict(get('producer')) return_obj.related_campaigns = RelatedCampaignRefs.from_dict(get('related_campaigns')) return_obj.related_packages = RelatedPackageRefs.from_dict(get('related_packages')) return return_obj
class Indicator(stix.BaseCoreComponent): """Implementation of the STIX Indicator. Args: id_ (optional): An identifier. If ``None``, a value will be generated via ``mixbox.idgen.create_id()``. If set, this will unset the ``idref`` property. idref (optional): An identifier reference. If set this will unset the ``id_`` property. title (optional): A string title. timestamp (optional): A timestamp value. Can be an instance of ``datetime.datetime`` or ``str``. description (optional): A string description. short_description (optional): A string short description. """ _binding = indicator_binding _binding_class = indicator_binding.IndicatorType _namespace = 'http://stix.mitre.org/Indicator-2' _version = "2.2" _ALL_VERSIONS = ("2.0", "2.0.1", "2.1", "2.1.1", "2.2") _ALLOWED_COMPOSITION_OPERATORS = ('AND', 'OR') _ID_PREFIX = "indicator" _try_cast = False producer = fields.TypedField("Producer", InformationSource) observable = fields.TypedField("Observable", Observable) indicator_types = VocabField("Type", IndicatorType, multiple=True, key_name="indicator_types") confidence = fields.TypedField("Confidence", Confidence) indicated_ttps = fields.TypedField("Indicated_TTP", RelatedTTP, multiple=True, key_name="indicated_ttps") test_mechanisms = fields.TypedField("Test_Mechanisms", TestMechanisms) alternative_id = fields.TypedField("Alternative_ID", multiple=True) suggested_coas = fields.TypedField("Suggested_COAs", SuggestedCOAs) sightings = fields.TypedField("Sightings", Sightings) composite_indicator_expression = fields.TypedField( "Composite_Indicator_Expression", "stix.indicator.CompositeIndicatorExpression") kill_chain_phases = fields.TypedField("Kill_Chain_Phases", KillChainPhasesReference) valid_time_positions = fields.TypedField("Valid_Time_Position", ValidTime, multiple=True, key_name="valid_time_positions") related_indicators = fields.TypedField("Related_Indicators", RelatedIndicators) related_campaigns = fields.TypedField( "Related_Campaigns", type_="stix.indicator.RelatedCampaignRefs") likely_impact = fields.TypedField("Likely_Impact", Statement) negate = fields.TypedField("negate") related_packages = fields.TypedField("Related_Packages", RelatedPackageRefs) def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): super(Indicator, self).__init__(id_=id_, idref=idref, timestamp=timestamp, title=title, description=description, short_description=short_description) self.observable = None self.indicator_types = IndicatorTypes() self.test_mechanisms = TestMechanisms() self.alternative_id = None self.suggested_coas = SuggestedCOAs() self.sightings = Sightings() self.composite_indicator_expression = None self.kill_chain_phases = KillChainPhasesReference() self.related_indicators = RelatedIndicators() self.related_campaigns = RelatedCampaignRefs() self.observable_composition_operator = "OR" self.related_packages = RelatedPackageRefs() @property def observables(self): """A list of ``cybox.core.Observable`` instances. This can be set to a single object instance or a list of objects. Note: If only one Observable is set, this property will return a list with the ``observable`` property. If multiple ``cybox.core.Observable`` this property will return Observables under the ``cybox.core.ObservableComposition``. Access to the top level ``cybox.core.Observable`` is made via ``observable`` property. Default Value: Empty ``list``. Returns: A ``list`` of ``cybox.core.Observable`` instances. """ if not self.observable: return [] elif self.observable.observable_composition: return self.observable.observable_composition.observables return [] @observables.setter def observables(self, value): """ The method will automatically create a top ``cybox.core.Observable`` and append all ``cybox.core.Observable`` using ``observable_composition`` property when a ``list`` is given with length greater than 1. Note: The top level ``cybox.core.Observable`` will set the ``operator`` property for the ``cybox.core.ObservableComposition`` via the ``observable_composition_operator`` property. The value of ``operator`` can be changed via ``observable_composition_operator`` property. By default, the composition layer will be set to ``"OR"``. Args: value: A ``list`` of ``cybox.core.Observable`` instances or a single ``cybox.core.Observable`` instance. Raises: ValueError: If set to a value that cannot be converted to an instance of ``cybox.core.Observable``. """ if not value: return if isinstance(value, Observable): self.observable = value elif utils.is_sequence(value): if len(value) == 1: self.observable = value return observable_comp = ObservableComposition() observable_comp.operator = self.observable_composition_operator for element in value: observable_comp.add(element) self.observable = Observable() self.observable.observable_composition = observable_comp def set_observables(self, value): self.observables = value def add_observable(self, observable): """Adds an observable to the ``observable`` property of the :class:`Indicator`. If the `observable` parameter is ``None``, no item will be added to the ``observable`` property. Note: The STIX Language dictates that an :class:`Indicator` can have only one ``Observable`` under it. Because of this, when a user adds another ``Observable`` a new, empty ``Observable`` will be crated and append the existing and new ``observable`` using the ``ObservableComposition`` property. To access the top level ``Observable`` can be achieved by the ``observable`` property .By default, the ``operator`` of the composition layer will be set to ``"OR"``. The ``operator`` value can be changed via the ``observable_composition_operator`` property. Setting ``observable`` or ``observables`` with re-initialize the property and lose all ``Observable`` in the composition layer. Args: observable: An instance of ``cybox.core.Observable`` or an object type that can be converted into one. Raises: ValueError: If the `observable` param cannot be converted into an instance of ``cybox.core.Observable``. """ if not observable: return # Sets the first observable. elif not self.observable: self.observable = observable # When another is inserted. A "root" Observable is created and the # user's Observables are appended to the composition. elif not self.observable.observable_composition: observable_comp = ObservableComposition() observable_comp.operator = self.observable_composition_operator observable_comp.add(self.observable) observable_comp.add(observable) self.observable = Observable() self.observable.observable_composition = observable_comp # Keep appending to "root" Observable. else: self.observable.observable_composition.add(observable) def add_alternative_id(self, value): """Adds an alternative id to the ``alternative_id`` list property. Note: If ``None`` is passed in no value is added to the ``alternative_id`` list property. Args: value: An identifier value. """ if not value: return self.alternative_id.append(value) def add_valid_time_position(self, value): """Adds an valid time position to the ``valid_time_positions`` property list. If `value` is ``None``, no item is added to the ``value_time_positions`` list. Args: value: An instance of :class:`stix.indicator.valid_time.ValidTime`. Raises: ValueError: If the `value` argument is not an instance of :class:`stix.indicator.valid_time.ValidTime`. """ self.valid_time_positions.append(value) def add_indicator_type(self, value): """Adds a value to the ``indicator_types`` list property. The `value` parameter can be a ``str`` or an instance of :class:`stix.common.vocabs.VocabString`. Note: If the `value` parameter is a ``str`` instance, an attempt will be made to convert it into an instance of :class:`stix.common.vocabs.IndicatorType` Args: value: An instance of :class:`stix.common.vocabs.VocabString` or ``str``. Raises: ValueError: If the `value` param is a ``str`` instance that cannot be converted into an instance of :class:`stix.common.vocabs.IndicatorType`. """ self.indicator_types.append(value) def add_indicated_ttp(self, v): """Adds an Indicated TTP to the ``indicated_ttps`` list property of this :class:`Indicator`. The `v` parameter must be an instance of :class:`stix.common.related.RelatedTTP` or :class:`stix.ttp.TTP`. If the `v` parameter is ``None``, no item wil be added to the ``indicated_ttps`` list property. Note: If the `v` parameter is not an instance of :class:`stix.common.related.RelatedTTP` an attempt will be made to convert it to one. Args: v: An instance of :class:`stix.common.related.RelatedTTP` or :class:`stix.ttp.TTP`. Raises: ValueError: If the `v` parameter cannot be converted into an instance of :class:`stix.common.related.RelatedTTP` """ self.indicated_ttps.append(v) def add_test_mechanism(self, tm): """Adds an Test Mechanism to the ``test_mechanisms`` list property of this :class:`Indicator`. The `tm` parameter must be an instance of a :class:`stix.indicator.test_mechanism._BaseTestMechanism` implementation. If the `tm` parameter is ``None``, no item will be added to the ``test_mechanisms`` list property. See Also: Test Mechanism implementations are found under the :mod:`stix.extensions.test_mechanism` package. Args: tm: An instance of a :class:`stix.indicator.test_mechanism._BaseTestMechanism` implementation. Raises: ValueError: If the `tm` parameter is not an instance of :class:`stix.indicator.test_mechanism._BaseTestMechanism` """ self.test_mechanisms.append(tm) def add_related_indicator(self, indicator): """Adds an Related Indicator to the ``related_indicators`` list property of this :class:`Indicator`. The `indicator` parameter must be an instance of :class:`stix.common.related.RelatedIndicator` or :class:`Indicator`. If the `indicator` parameter is ``None``, no item wil be added to the ``related_indicators`` list property. Calling this method is the same as calling ``append()`` on the ``related_indicators`` proeprty. See Also: The :class:`RelatedIndicators` documentation. Note: If the `tm` parameter is not an instance of :class:`stix.common.related.RelatedIndicator` an attempt will be made to convert it to one. Args: indicator: An instance of :class:`Indicator` or :class:`stix.common.related.RelatedIndicator`. Raises: ValueError: If the `indicator` parameter cannot be converted into an instance of :class:`stix.common.related.RelatedIndicator` """ self.related_indicators.append(indicator) def add_related_campaign(self, value): """Adds a Related Campaign to this Indicator. The `value` parameter must be an instance of :class:`.RelatedCampaignRef` or :class:`.CampaignRef`. If the `value` parameter is ``None``, no item wil be added to the ``related_campaigns`` collection. Calling this method is the same as calling ``append()`` on the ``related_campaigns`` property. See Also: The :class:`.RelatedCampaignRef` documentation. Note: If the `value` parameter is not an instance of :class:`.RelatedCampaignRef` an attempt will be made to convert it to one. Args: value: An instance of :class:`.RelatedCampaignRef` or :class:`.Campaign`. Raises: ValueError: If the `value` parameter cannot be converted into an instance of :class:`.RelatedCampaignRef` """ self.related_campaigns.append(value) @property def observable_composition_operator(self): return self._observable_composition_operator @observable_composition_operator.setter def observable_composition_operator(self, value): if value in self._ALLOWED_COMPOSITION_OPERATORS: self._observable_composition_operator = value if self.observable and self.observable.observable_composition: self.observable.observable_composition.operator = value return error = "observable_composition_operator must one of {0}" error = error.format(self._ALLOWED_COMPOSITION_OPERATORS) raise ValueError(error) def add_kill_chain_phase(self, value): """Add a new Kill Chain Phase reference to this Indicator. Args: value: a :class:`stix.common.kill_chains.KillChainPhase` or a `str` representing the phase_id of. Note that you if you are defining a custom Kill Chain, you need to add it to the STIX package separately. """ self.kill_chain_phases.append(value) def add_related_package(self, value): self.related_packages.append(value) def set_producer_identity(self, identity): """Sets the name of the producer of this indicator. This is the same as calling ``indicator.producer.identity.name = identity``. If the ``producer`` property is ``None``, it will be initialized to an instance of :class:`stix.common.information_source.InformationSource`. If the ``identity`` property of the ``producer`` instance is ``None``, it will be initialized to an instance of :class:`stix.common.identity.Identity`. Note: if the `identity` parameter is not an instance :class:`stix.common.identity.Identity` an attempt will be made to convert it to one. Args: identity: An instance of ``str`` or ``stix.common.identity.Identity``. """ def unset_producer_identity(): try: self.producer.identity.name = None except AttributeError: pass if not identity: unset_producer_identity() return if not self.producer: self.producer = InformationSource() if isinstance(identity, Identity): self.producer.identity = identity return if not self.producer.identity: self.producer.identity = Identity() self.producer.identity.name = str(identity) def set_produced_time(self, produced_time): """Sets the ``produced_time`` property of the ``producer`` property instance fo `produced_time`. This is the same as calling ``indicator.producer.time.produced_time = produced_time``. The `produced_time` parameter must be an instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Note: If `produced_time` is a ``str`` or ``datetime.datetime`` instance an attempt will be made to convert it into an instance of ``cybox.common.DateTimeWithPrecision``. Args: produced_time: An instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. """ if not self.producer: self.producer = InformationSource() if not self.producer.time: self.producer.time = Time() self.producer.time.produced_time = produced_time def get_produced_time(self): """Gets the produced time for this :class:`Indicator`. This is the same as calling ``produced_time = indicator.producer.time.produced_time``. Returns: ``None`` or an instance of ``cybox.common.DateTimeWithPrecision``. """ try: return self.producer.time.produced_time except AttributeError: return None def set_received_time(self, received_time): """Sets the received time for this :class:`Indicator`. This is the same as calling ``indicator.producer.time.produced_time = produced_time``. The `received_time` parameter must be an instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Args: received_time: An instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Note: If `received_time` is a ``str`` or ``datetime.datetime`` instance an attempt will be made to convert it into an instance of ``cybox.common.DateTimeWithPrecision``. """ if not self.producer: self.producer = InformationSource() if not self.producer.time: self.producer.time = Time() self.producer.time.received_time = received_time def get_received_time(self): """Gets the received time for this :class:`Indicator`. This is the same as calling ``received_time = indicator.producer.time.received_time``. Returns: ``None`` or an instance of ``cybox.common.DateTimeWithPrecision``. """ try: return self.producer.time.received_time except AttributeError: return None def _merge_observables(self, observables): observable_composition = ObservableComposition() observable_composition.operator = self.observable_composition_operator for observable in observables: observable_composition.add(observable) root_observable = Observable() root_observable.observable_composition = observable_composition return root_observable def add_object(self, object_): """Adds a python-cybox Object instance to the ``observables`` list property. This is the same as calling ``indicator.add_observable(object_)``. Note: If the `object` param is not an instance of ``cybox.core.Object`` an attempt will be made to to convert it into one before wrapping it in an ``cybox.core.Observable`` layer. Args: object_: An instance of ``cybox.core.Object`` or an object that can be converted into an instance of ``cybox.core.Observable`` Raises: ValueError: if the `object_` param cannot be converted to an instance of ``cybox.core.Observable``. """ if not object_: return observable = Observable(object_) self.add_observable(observable) def _finalize_obj(self, entity_obj): """Omits the `negate` field if it is not equal to True. """ if self.negate: entity_obj.negate = True elif hasattr(entity_obj, 'negate'): entity_obj.negate = None def _finalize_dict(self, entity_dict): """Omits the `negate` field if it is not equal to True. """ if self.negate: entity_dict['negate'] = True elif 'negate' in entity_dict: del entity_dict['negate']
ttp.add_intended_effect(IntendedEffect('Account Takeover')) # TTP - Attack Pattern attack_pattern = AttackPattern() attack_pattern.capec_id = 'CAPEC-98' attack_pattern.description = 'Phishing' attack_pattern.short_description = 'Phishing' ttp.behavior = Behavior() ttp.behavior.add_attack_pattern(attack_pattern) # TTP - Kill Chain Phase phase = KillChainPhase( name='Infect Machine', phase_id='example:TTP-7a0fb8e4-a778-4c79-9c7e-8747675da5f1') kc_phases = KillChainPhasesReference() kc_phases.append(KillChainPhaseReference(name=phase.name)) ttp.kill_chain_phases = kc_phases # TTP - Resource (Tool, Infrastructure, Personas) resource = Resource() tool = ToolInformation(title='malware.exe') tool.type_ = AttackerToolType('Malware') tool.description = 'Tool Description' tool.short_description = 'Tool Short Description' infrastructure = Infrastructure(title='Leveraged Domains') infrastructure.types = AttackerInfrastructureType('Domain Registration') infrastructure.description = 'Infrastructure Description' infrastructure.short_description = 'Infrastructure Short Description' domain = DomainName()
class Indicator(stix.BaseCoreComponent): """Implementation of the STIX Indicator. Args: id_ (optional): An identifier. If ``None``, a value will be generated via ``mixbox.idgen.create_id()``. If set, this will unset the ``idref`` property. idref (optional): An identifier reference. If set this will unset the ``id_`` property. title (optional): A string title. timestamp (optional): A timestamp value. Can be an instance of ``datetime.datetime`` or ``str``. description (optional): A string description. short_description (optional): A string short description. """ _binding = indicator_binding _binding_class = indicator_binding.IndicatorType _namespace = 'http://stix.mitre.org/Indicator-2' _version = "2.2" _ALL_VERSIONS = ("2.0", "2.0.1", "2.1", "2.1.1", "2.2") _ALLOWED_COMPOSITION_OPERATORS = ('AND', 'OR') _ID_PREFIX = "indicator" _try_cast = False producer = fields.TypedField("Producer", InformationSource) observable = fields.TypedField("Observable", Observable) indicator_types = VocabField("Type", IndicatorType, multiple=True, key_name="indicator_types") confidence = fields.TypedField("Confidence", Confidence) indicated_ttps = fields.TypedField("Indicated_TTP", RelatedTTP, multiple=True, key_name="indicated_ttps") test_mechanisms = fields.TypedField("Test_Mechanisms", TestMechanisms) alternative_id = fields.TypedField("Alternative_ID", multiple=True) suggested_coas = fields.TypedField("Suggested_COAs", SuggestedCOAs) sightings = fields.TypedField("Sightings", Sightings) composite_indicator_expression = fields.TypedField("Composite_Indicator_Expression", "stix.indicator.CompositeIndicatorExpression") kill_chain_phases = fields.TypedField("Kill_Chain_Phases", KillChainPhasesReference) valid_time_positions = fields.TypedField("Valid_Time_Position", ValidTime, multiple=True, key_name="valid_time_positions") related_indicators = fields.TypedField("Related_Indicators", RelatedIndicators) related_campaigns = fields.TypedField("Related_Campaigns", type_="stix.indicator.RelatedCampaignRefs") likely_impact = fields.TypedField("Likely_Impact", Statement) negate = fields.TypedField("negate") related_packages = fields.TypedField("Related_Packages", RelatedPackageRefs) def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): super(Indicator, self).__init__( id_=id_, idref=idref, timestamp=timestamp, title=title, description=description, short_description=short_description ) self.observable = None self.indicator_types = IndicatorTypes() self.test_mechanisms = TestMechanisms() self.alternative_id = None self.suggested_coas = SuggestedCOAs() self.sightings = Sightings() self.composite_indicator_expression = None self.kill_chain_phases = KillChainPhasesReference() self.related_indicators = RelatedIndicators() self.related_campaigns = RelatedCampaignRefs() self.observable_composition_operator = "OR" self.related_packages = RelatedPackageRefs() @property def observables(self): """A list of ``cybox.core.Observable`` instances. This can be set to a single object instance or a list of objects. Note: If only one Observable is set, this property will return a list with the ``observable`` property. If multiple ``cybox.core.Observable`` this property will return Observables under the ``cybox.core.ObservableComposition``. Access to the top level ``cybox.core.Observable`` is made via ``observable`` property. Default Value: Empty ``list``. Returns: A ``list`` of ``cybox.core.Observable`` instances. """ if not self.observable: return [] elif self.observable.observable_composition: return self.observable.observable_composition.observables # self.observable is defined and not a composition. return [self.observable] @observables.setter def observables(self, value): """ The method will automatically create a top ``cybox.core.Observable`` and append all ``cybox.core.Observable`` using ``observable_composition`` property when a ``list`` is given with length greater than 1. Note: The top level ``cybox.core.Observable`` will set the ``operator`` property for the ``cybox.core.ObservableComposition`` via the ``observable_composition_operator`` property. The value of ``operator`` can be changed via ``observable_composition_operator`` property. By default, the composition layer will be set to ``"OR"``. Args: value: A ``list`` of ``cybox.core.Observable`` instances or a single ``cybox.core.Observable`` instance. Raises: ValueError: If set to a value that cannot be converted to an instance of ``cybox.core.Observable``. """ if not value: return if isinstance(value, Observable): self.observable = value elif utils.is_sequence(value): if len(value) == 1: self.add_observable(value[0]) return observable_comp = ObservableComposition() observable_comp.operator = self.observable_composition_operator for element in value: observable_comp.add(element) self.observable = Observable() self.observable.observable_composition = observable_comp def set_observables(self, value): self.observables = value def add_observable(self, observable): """Adds an observable to the ``observable`` property of the :class:`Indicator`. If the `observable` parameter is ``None``, no item will be added to the ``observable`` property. Note: The STIX Language dictates that an :class:`Indicator` can have only one ``Observable`` under it. Because of this, when a user adds another ``Observable`` a new, empty ``Observable`` will be crated and append the existing and new ``observable`` using the ``ObservableComposition`` property. To access the top level ``Observable`` can be achieved by the ``observable`` property .By default, the ``operator`` of the composition layer will be set to ``"OR"``. The ``operator`` value can be changed via the ``observable_composition_operator`` property. Setting ``observable`` or ``observables`` with re-initialize the property and lose all ``Observable`` in the composition layer. Args: observable: An instance of ``cybox.core.Observable`` or an object type that can be converted into one. Raises: ValueError: If the `observable` param cannot be converted into an instance of ``cybox.core.Observable``. """ if not observable: return # Sets the first observable. elif not self.observable: self.observable = observable # When another is inserted. A "root" Observable is created and the # user's Observables are appended to the composition. elif not self.observable.observable_composition: observable_comp = ObservableComposition() observable_comp.operator = self.observable_composition_operator observable_comp.add(self.observable) observable_comp.add(observable) self.observable = Observable() self.observable.observable_composition = observable_comp # Keep appending to "root" Observable. else: self.observable.observable_composition.add(observable) def add_alternative_id(self, value): """Adds an alternative id to the ``alternative_id`` list property. Note: If ``None`` is passed in no value is added to the ``alternative_id`` list property. Args: value: An identifier value. """ if not value: return self.alternative_id.append(value) def add_valid_time_position(self, value): """Adds an valid time position to the ``valid_time_positions`` property list. If `value` is ``None``, no item is added to the ``value_time_positions`` list. Args: value: An instance of :class:`stix.indicator.valid_time.ValidTime`. Raises: ValueError: If the `value` argument is not an instance of :class:`stix.indicator.valid_time.ValidTime`. """ self.valid_time_positions.append(value) def add_indicator_type(self, value): """Adds a value to the ``indicator_types`` list property. The `value` parameter can be a ``str`` or an instance of :class:`stix.common.vocabs.VocabString`. Note: If the `value` parameter is a ``str`` instance, an attempt will be made to convert it into an instance of :class:`stix.common.vocabs.IndicatorType` Args: value: An instance of :class:`stix.common.vocabs.VocabString` or ``str``. Raises: ValueError: If the `value` param is a ``str`` instance that cannot be converted into an instance of :class:`stix.common.vocabs.IndicatorType`. """ self.indicator_types.append(value) def add_indicated_ttp(self, v): """Adds an Indicated TTP to the ``indicated_ttps`` list property of this :class:`Indicator`. The `v` parameter must be an instance of :class:`stix.common.related.RelatedTTP` or :class:`stix.ttp.TTP`. If the `v` parameter is ``None``, no item wil be added to the ``indicated_ttps`` list property. Note: If the `v` parameter is not an instance of :class:`stix.common.related.RelatedTTP` an attempt will be made to convert it to one. Args: v: An instance of :class:`stix.common.related.RelatedTTP` or :class:`stix.ttp.TTP`. Raises: ValueError: If the `v` parameter cannot be converted into an instance of :class:`stix.common.related.RelatedTTP` """ self.indicated_ttps.append(v) def add_test_mechanism(self, tm): """Adds an Test Mechanism to the ``test_mechanisms`` list property of this :class:`Indicator`. The `tm` parameter must be an instance of a :class:`stix.indicator.test_mechanism._BaseTestMechanism` implementation. If the `tm` parameter is ``None``, no item will be added to the ``test_mechanisms`` list property. See Also: Test Mechanism implementations are found under the :mod:`stix.extensions.test_mechanism` package. Args: tm: An instance of a :class:`stix.indicator.test_mechanism._BaseTestMechanism` implementation. Raises: ValueError: If the `tm` parameter is not an instance of :class:`stix.indicator.test_mechanism._BaseTestMechanism` """ self.test_mechanisms.append(tm) def add_related_indicator(self, indicator): """Adds an Related Indicator to the ``related_indicators`` list property of this :class:`Indicator`. The `indicator` parameter must be an instance of :class:`stix.common.related.RelatedIndicator` or :class:`Indicator`. If the `indicator` parameter is ``None``, no item wil be added to the ``related_indicators`` list property. Calling this method is the same as calling ``append()`` on the ``related_indicators`` proeprty. See Also: The :class:`RelatedIndicators` documentation. Note: If the `tm` parameter is not an instance of :class:`stix.common.related.RelatedIndicator` an attempt will be made to convert it to one. Args: indicator: An instance of :class:`Indicator` or :class:`stix.common.related.RelatedIndicator`. Raises: ValueError: If the `indicator` parameter cannot be converted into an instance of :class:`stix.common.related.RelatedIndicator` """ self.related_indicators.append(indicator) def add_related_campaign(self, value): """Adds a Related Campaign to this Indicator. The `value` parameter must be an instance of :class:`.RelatedCampaignRef` or :class:`.CampaignRef`. If the `value` parameter is ``None``, no item wil be added to the ``related_campaigns`` collection. Calling this method is the same as calling ``append()`` on the ``related_campaigns`` property. See Also: The :class:`.RelatedCampaignRef` documentation. Note: If the `value` parameter is not an instance of :class:`.RelatedCampaignRef` an attempt will be made to convert it to one. Args: value: An instance of :class:`.RelatedCampaignRef` or :class:`.Campaign`. Raises: ValueError: If the `value` parameter cannot be converted into an instance of :class:`.RelatedCampaignRef` """ self.related_campaigns.append(value) @property def observable_composition_operator(self): return self._observable_composition_operator @observable_composition_operator.setter def observable_composition_operator(self, value): if value in self._ALLOWED_COMPOSITION_OPERATORS: self._observable_composition_operator = value if self.observable and self.observable.observable_composition: self.observable.observable_composition.operator = value return error = "observable_composition_operator must one of {0}" error = error.format(self._ALLOWED_COMPOSITION_OPERATORS) raise ValueError(error) def add_kill_chain_phase(self, value): """Add a new Kill Chain Phase reference to this Indicator. Args: value: a :class:`stix.common.kill_chains.KillChainPhase` or a `str` representing the phase_id of. Note that you if you are defining a custom Kill Chain, you need to add it to the STIX package separately. """ self.kill_chain_phases.append(value) def add_related_package(self, value): self.related_packages.append(value) def set_producer_identity(self, identity): """Sets the name of the producer of this indicator. This is the same as calling ``indicator.producer.identity.name = identity``. If the ``producer`` property is ``None``, it will be initialized to an instance of :class:`stix.common.information_source.InformationSource`. If the ``identity`` property of the ``producer`` instance is ``None``, it will be initialized to an instance of :class:`stix.common.identity.Identity`. Note: if the `identity` parameter is not an instance :class:`stix.common.identity.Identity` an attempt will be made to convert it to one. Args: identity: An instance of ``str`` or ``stix.common.identity.Identity``. """ def unset_producer_identity(): try: self.producer.identity.name = None except AttributeError: pass if not identity: unset_producer_identity() return if not self.producer: self.producer = InformationSource() if isinstance(identity, Identity): self.producer.identity = identity return if not self.producer.identity: self.producer.identity = Identity() self.producer.identity.name = str(identity) def set_produced_time(self, produced_time): """Sets the ``produced_time`` property of the ``producer`` property instance fo `produced_time`. This is the same as calling ``indicator.producer.time.produced_time = produced_time``. The `produced_time` parameter must be an instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Note: If `produced_time` is a ``str`` or ``datetime.datetime`` instance an attempt will be made to convert it into an instance of ``cybox.common.DateTimeWithPrecision``. Args: produced_time: An instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. """ if not self.producer: self.producer = InformationSource() if not self.producer.time: self.producer.time = Time() self.producer.time.produced_time = produced_time def get_produced_time(self): """Gets the produced time for this :class:`Indicator`. This is the same as calling ``produced_time = indicator.producer.time.produced_time``. Returns: ``None`` or an instance of ``cybox.common.DateTimeWithPrecision``. """ try: return self.producer.time.produced_time except AttributeError: return None def set_received_time(self, received_time): """Sets the received time for this :class:`Indicator`. This is the same as calling ``indicator.producer.time.produced_time = produced_time``. The `received_time` parameter must be an instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Args: received_time: An instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Note: If `received_time` is a ``str`` or ``datetime.datetime`` instance an attempt will be made to convert it into an instance of ``cybox.common.DateTimeWithPrecision``. """ if not self.producer: self.producer = InformationSource() if not self.producer.time: self.producer.time = Time() self.producer.time.received_time = received_time def get_received_time(self): """Gets the received time for this :class:`Indicator`. This is the same as calling ``received_time = indicator.producer.time.received_time``. Returns: ``None`` or an instance of ``cybox.common.DateTimeWithPrecision``. """ try: return self.producer.time.received_time except AttributeError: return None def _merge_observables(self, observables): observable_composition = ObservableComposition() observable_composition.operator = self.observable_composition_operator for observable in observables: observable_composition.add(observable) root_observable = Observable() root_observable.observable_composition = observable_composition return root_observable def add_object(self, object_): """Adds a python-cybox Object instance to the ``observables`` list property. This is the same as calling ``indicator.add_observable(object_)``. Note: If the `object` param is not an instance of ``cybox.core.Object`` an attempt will be made to to convert it into one before wrapping it in an ``cybox.core.Observable`` layer. Args: object_: An instance of ``cybox.core.Object`` or an object that can be converted into an instance of ``cybox.core.Observable`` Raises: ValueError: if the `object_` param cannot be converted to an instance of ``cybox.core.Observable``. """ if not object_: return observable = Observable(object_) self.add_observable(observable) def _finalize_obj(self, entity_obj): """Omits the `negate` field if it is not equal to True. """ if self.negate: entity_obj.negate = True elif hasattr(entity_obj, 'negate'): entity_obj.negate = None def _finalize_dict(self, entity_dict): """Omits the `negate` field if it is not equal to True. """ if self.negate: entity_dict['negate'] = True elif 'negate' in entity_dict: del entity_dict['negate']
def test_add_no_id_phase(self): refs = KillChainPhasesReference() phase = KillChainPhase() self.assertRaises(ValueError, refs.append, phase)
class Indicator(stix.BaseCoreComponent): """Implementation of the STIX Indicator. Args: id_ (optional): An identifier. If ``None``, a value will be generated via ``mixbox.idgen.create_id()``. If set, this will unset the ``idref`` property. idref (optional): An identifier reference. If set this will unset the ``id_`` property. title (optional): A string title. timestamp (optional): A timestamp value. Can be an instance of ``datetime.datetime`` or ``str``. description (optional): A string description. short_description (optional): A string short description. """ _binding = indicator_binding _binding_class = indicator_binding.IndicatorType _namespace = 'http://stix.mitre.org/Indicator-2' _version = "2.2" _ALL_VERSIONS = ("2.0", "2.0.1", "2.1", "2.1.1", "2.2") _ALLOWED_COMPOSITION_OPERATORS = ('AND', 'OR') _ID_PREFIX = "indicator" def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): super(Indicator, self).__init__(id_=id_, idref=idref, timestamp=timestamp, title=title, description=description, short_description=short_description) self.producer = None self.observables = None self.indicator_types = IndicatorTypes() self.confidence = None self.indicated_ttps = _IndicatedTTPs() self.test_mechanisms = TestMechanisms() self.alternative_id = None self.suggested_coas = SuggestedCOAs() self.sightings = Sightings() self.composite_indicator_expression = None self.kill_chain_phases = KillChainPhasesReference() self.valid_time_positions = _ValidTimePositions() self.related_indicators = None self.related_campaigns = RelatedCampaignRefs() self.observable_composition_operator = "OR" self.likely_impact = None self.negate = None self.related_packages = RelatedPackageRefs() @property def producer(self): """Contains information about the source of the :class:`Indicator`. Default Value: ``None`` Returns: An instance of :class:`stix.common.information_source.InformationSource` Raises: ValueError: If set to a value that is not ``None`` and not an instance of :class:`stix.common.information_source.InformationSource` """ return self._producer @producer.setter def producer(self, value): self._set_var(InformationSource, try_cast=False, producer=value) @property def observable(self): """A convenience property for accessing or setting the only ``cybox.core.Observable`` instance held by this Indicator. Default Value: Empty ``list``. Setting this property results in the ``observables`` property being reinitialized to an empty ``list`` and appending the input value, resulting in a ``list`` containing one value. Note: If the ``observables`` list contains more than one item, this property will only return the first item in the list. Returns: An instance of ``cybox.core.Observable``. Raises: ValueError: If set to a value that cannot be converted to an instance of ``cybox.core.Observable``. """ if self.observables: return self.observables[0] else: return None @observable.setter def observable(self, observable): self._observables = _Observables(observable) @property def observables(self): """A list of ``cybox.core.Observable`` instances. This can be set to a single object instance or a list of objects. Note: If the input value or values are not instance(s) of ``cybox.core.Observable``, an attempt will be made to convert the value to an instance of ``cybox.core.Observable``. Default Value: Empty ``list`` Returns: A ``list`` of ``cybox.core.Observable`` instances. Raises: ValueError: If set to a value that cannot be converted to an instance of ``cybox.core.Observable``. """ return self._observables @observables.setter def observables(self, value): self._observables = _Observables(value) def add_observable(self, observable): """Adds an observable to the ``observables`` list property of the :class:`Indicator`. If the `observable` parameter is ``None``, no item will be added to the ``observables`` list. Note: The STIX Language dictates that an :class:`Indicator` can have only one ``Observable`` under it. Because of this, the ``to_xml()`` method will convert the ``observables`` list into an ``cybox.core.ObservableComposition`` instance, in which each item in the ``observables`` list will be added to the composition. By default, the ``operator`` of the composition layer will be set to ``"OR"``. The ``operator`` value can be changed via the ``observable_composition_operator`` property. Args: observable: An instance of ``cybox.core.Observable`` or an object type that can be converted into one. Raises: ValueError: If the `observable` param cannot be converted into an instance of ``cybox.core.Observable``. """ self.observables.append(observable) @property def alternative_id(self): """An alternative identifi er for this :class:`Indicator` This property can be set to a single string identifier or a list of identifiers. If set to a single object, the object will be inserted into an empty list internally. Default Value: Empty ``list`` Returns: A list of alternative ids. """ return self._alternative_id @alternative_id.setter def alternative_id(self, value): self._alternative_id = [] if not value: return elif utils.is_sequence(value): self._alternative_id.extend(x for x in value if x) else: self._alternative_id.append(value) def add_alternative_id(self, value): """Adds an alternative id to the ``alternative_id`` list property. Note: If ``None`` is passed in no value is added to the ``alternative_id`` list property. Args: value: An identifier value. """ if not value: return self.alternative_id.append(value) @property def valid_time_positions(self): """A list of valid time positions for this :class:`Indicator`. This property can be set to a single instance or a list of :class:`stix.indicator.valid_time.ValidTime` instances. If set to a single instance, that object is converted into a list containing one item. Default Value: Empty ``list`` Returns: A list of :class:`stix.indicator.valid_time.ValidTime` instances. """ return self._valid_time_positions @valid_time_positions.setter def valid_time_positions(self, value): self._valid_time_positions = _ValidTimePositions(value) def add_valid_time_position(self, value): """Adds an valid time position to the ``valid_time_positions`` property list. If `value` is ``None``, no item is added to the ``value_time_positions`` list. Args: value: An instance of :class:`stix.indicator.valid_time.ValidTime`. Raises: ValueError: If the `value` argument is not an instance of :class:`stix.indicator.valid_time.ValidTime`. """ self.valid_time_positions.append(value) @property def indicator_types(self): """A list of indicator types for this :class:`Indicator`. This property can be set to lists or single instances of ``str`` or :class:`stix.common.vocabs.VocabString` or an instance of :class:`IndicatorTypes`. Note: If an instance of ``str`` is passed in (or a ``list`` containing ``str`` values) an attempt will be made to convert that string value to an instance of :class:`stix.common.vocabs.IndicatorType`. Default Value: An empty ``IndicatorTypes`` instance. See Also: Documentation for :class:`IndicatorTypes`. Returns: An instance of ``IndicatorTypes``. """ return self._indicator_types @indicator_types.setter def indicator_types(self, value): self._indicator_types = IndicatorTypes(value) def add_indicator_type(self, value): """Adds a value to the ``indicator_types`` list property. The `value` parameter can be a ``str`` or an instance of :class:`stix.common.vocabs.VocabString`. Note: If the `value` parameter is a ``str`` instance, an attempt will be made to convert it into an instance of :class:`stix.common.vocabs.IndicatorType` Args: value: An instance of :class:`stix.common.vocabs.VocabString` or ``str``. Raises: ValueError: If the `value` param is a ``str`` instance that cannot be converted into an instance of :class:`stix.common.vocabs.IndicatorType`. """ self.indicator_types.append(value) @property def confidence(self): """The confidence for this :class:`Indicator`. This property can be set to an instance of ``str``, :class:`stix.common.vocabs.VocabString`, or :class:`stix.common.confidence.Confidence`. Default Value: ``None`` Note: If set to an instance of ``str`` or :class:`stix.common.vocabs.VocabString`, that value will be wrapped in an instance of :class:`stix.common.confidence.Confidence`. Returns: An instance of of :class:`stix.common.confidence.Confidence`. Raises: ValueError: If set to a ``str`` value that cannot be converted into an instance of :class:`stix.common.confidence.Confidence`. """ return self._confidence @confidence.setter def confidence(self, value): self._set_var(Confidence, confidence=value) @property def indicated_ttps(self): return self._indicated_ttps @indicated_ttps.setter def indicated_ttps(self, value): self._indicated_ttps = _IndicatedTTPs(value) def add_indicated_ttp(self, v): """Adds an Indicated TTP to the ``indicated_ttps`` list property of this :class:`Indicator`. The `v` parameter must be an instance of :class:`stix.common.related.RelatedTTP` or :class:`stix.ttp.TTP`. If the `v` parameter is ``None``, no item wil be added to the ``indicated_ttps`` list property. Note: If the `v` parameter is not an instance of :class:`stix.common.related.RelatedTTP` an attempt will be made to convert it to one. Args: v: An instance of :class:`stix.common.related.RelatedTTP` or :class:`stix.ttp.TTP`. Raises: ValueError: If the `v` parameter cannot be converted into an instance of :class:`stix.common.related.RelatedTTP` """ self.indicated_ttps.append(v) @property def test_mechanisms(self): return self._test_mechanisms @test_mechanisms.setter def test_mechanisms(self, value): self._test_mechanisms = TestMechanisms(value) def add_test_mechanism(self, tm): """Adds an Test Mechanism to the ``test_mechanisms`` list property of this :class:`Indicator`. The `tm` parameter must be an instance of a :class:`stix.indicator.test_mechanism._BaseTestMechanism` implementation. If the `tm` parameter is ``None``, no item will be added to the ``test_mechanisms`` list property. See Also: Test Mechanism implementations are found under the :mod:`stix.extensions.test_mechanism` package. Args: tm: An instance of a :class:`stix.indicator.test_mechanism._BaseTestMechanism` implementation. Raises: ValueError: If the `tm` parameter is not an instance of :class:`stix.indicator.test_mechanism._BaseTestMechanism` """ self.test_mechanisms.append(tm) @property def related_indicators(self): return self._related_indicators @related_indicators.setter def related_indicators(self, value): if isinstance(value, RelatedIndicators): self._related_indicators = value else: self._related_indicators = RelatedIndicators(value) def add_related_indicator(self, indicator): """Adds an Related Indicator to the ``related_indicators`` list property of this :class:`Indicator`. The `indicator` parameter must be an instance of :class:`stix.common.related.RelatedIndicator` or :class:`Indicator`. If the `indicator` parameter is ``None``, no item wil be added to the ``related_indicators`` list property. Calling this method is the same as calling ``append()`` on the ``related_indicators`` proeprty. See Also: The :class:`RelatedIndicators` documentation. Note: If the `tm` parameter is not an instance of :class:`stix.common.related.RelatedIndicator` an attempt will be made to convert it to one. Args: indicator: An instance of :class:`Indicator` or :class:`stix.common.related.RelatedIndicator`. Raises: ValueError: If the `indicator` parameter cannot be converted into an instance of :class:`stix.common.related.RelatedIndicator` """ self.related_indicators.append(indicator) @property def related_campaigns(self): return self._related_campaigns @related_campaigns.setter def related_campaigns(self, value): if isinstance(value, RelatedCampaignRefs): self._related_campaigns = value else: self._related_campaigns = RelatedCampaignRefs(value) def add_related_campaign(self, value): """Adds a Related Campaign to this Indicator. The `value` parameter must be an instance of :class:`.RelatedCampaignRef` or :class:`.CampaignRef`. If the `value` parameter is ``None``, no item wil be added to the ``related_campaigns`` collection. Calling this method is the same as calling ``append()`` on the ``related_campaigns`` property. See Also: The :class:`.RelatedCampaignRef` documentation. Note: If the `value` parameter is not an instance of :class:`.RelatedCampaignRef` an attempt will be made to convert it to one. Args: value: An instance of :class:`.RelatedCampaignRef` or :class:`.Campaign`. Raises: ValueError: If the `value` parameter cannot be converted into an instance of :class:`.RelatedCampaignRef` """ self.related_campaigns.append(value) @property def observable_composition_operator(self): return self._observable_composition_operator @observable_composition_operator.setter def observable_composition_operator(self, value): if value in self._ALLOWED_COMPOSITION_OPERATORS: self._observable_composition_operator = value return error = "observable_composition_operator must one of {0}" error = error.format(self._ALLOWED_COMPOSITION_OPERATORS) raise ValueError(error) @property def likely_impact(self): return self._likely_impact @likely_impact.setter def likely_impact(self, value): self._set_var(Statement, likely_impact=value) @property def negate(self): return self._negate @negate.setter def negate(self, value): self._negate = utils.xml_bool(value) @property def kill_chain_phases(self): return self._kill_chain_phases @kill_chain_phases.setter def kill_chain_phases(self, value): self._kill_chain_phases = KillChainPhasesReference(value) def add_kill_chain_phase(self, value): """Add a new Kill Chain Phase reference to this Indicator. Args: value: a :class:`stix.common.kill_chains.KillChainPhase` or a `str` representing the phase_id of. Note that you if you are defining a custom Kill Chain, you need to add it to the STIX package separately. """ self.kill_chain_phases.append(value) @property def related_packages(self): return self._related_packages @related_packages.setter def related_packages(self, value): self._related_packages = RelatedPackageRefs(value) def add_related_package(self, value): self.related_packages.append(value) def set_producer_identity(self, identity): """Sets the name of the producer of this indicator. This is the same as calling ``indicator.producer.identity.name = identity``. If the ``producer`` property is ``None``, it will be initialized to an instance of :class:`stix.common.information_source.InformationSource`. If the ``identity`` property of the ``producer`` instance is ``None``, it will be initialized to an instance of :class:`stix.common.identity.Identity`. Note: if the `identity` parameter is not an instance :class:`stix.common.identity.Identity` an attempt will be made to convert it to one. Args: identity: An instance of ``str`` or ``stix.common.identity.Identity``. """ def unset_producer_identity(): try: self.producer.identity.name = None except AttributeError: pass if not identity: unset_producer_identity() return if not self.producer: self.producer = InformationSource() if isinstance(identity, Identity): self.producer.identity = identity return if not self.producer.identity: self.producer.identity = Identity() self.producer.identity.name = str(identity) def set_produced_time(self, produced_time): """Sets the ``produced_time`` property of the ``producer`` property instance fo `produced_time`. This is the same as calling ``indicator.producer.time.produced_time = produced_time``. The `produced_time` parameter must be an instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Note: If `produced_time` is a ``str`` or ``datetime.datetime`` instance an attempt will be made to convert it into an instance of ``cybox.common.DateTimeWithPrecision``. Args: produced_time: An instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. """ if not self.producer: self.producer = InformationSource() if not self.producer.time: self.producer.time = Time() self.producer.time.produced_time = produced_time def get_produced_time(self): """Gets the produced time for this :class:`Indicator`. This is the same as calling ``produced_time = indicator.producer.time.produced_time``. Returns: ``None`` or an instance of ``cybox.common.DateTimeWithPrecision``. """ try: return self.producer.time.produced_time except AttributeError: return None def set_received_time(self, received_time): """Sets the received time for this :class:`Indicator`. This is the same as calling ``indicator.producer.time.produced_time = produced_time``. The `received_time` parameter must be an instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Args: received_time: An instance of ``str``, ``datetime.datetime``, or ``cybox.common.DateTimeWithPrecision``. Note: If `received_time` is a ``str`` or ``datetime.datetime`` instance an attempt will be made to convert it into an instance of ``cybox.common.DateTimeWithPrecision``. """ if not self.producer: self.producer = InformationSource() if not self.producer.time: self.producer.time = Time() self.producer.time.received_time = received_time def get_received_time(self): """Gets the received time for this :class:`Indicator`. This is the same as calling ``received_time = indicator.producer.time.received_time``. Returns: ``None`` or an instance of ``cybox.common.DateTimeWithPrecision``. """ try: return self.producer.time.received_time except AttributeError: return None def _merge_observables(self, observables): observable_composition = ObservableComposition() observable_composition.operator = self.observable_composition_operator for observable in observables: observable_composition.add(observable) root_observable = Observable() root_observable.observable_composition = observable_composition return root_observable def add_object(self, object_): """Adds a python-cybox Object instance to the ``observables`` list property. This is the same as calling ``indicator.add_observable(object_)``. Note: If the `object` param is not an instance of ``cybox.core.Object`` an attempt will be made to to convert it into one before wrapping it in an ``cybox.core.Observable`` layer. Args: object_: An instance of ``cybox.core.Object`` or an object that can be converted into an instance of ``cybox.core.Observable`` Raises: ValueError: if the `object_` param cannot be converted to an instance of ``cybox.core.Observable``. """ if not object_: return observable = Observable(object_) self.add_observable(observable) def to_obj(self, return_obj=None, ns_info=None): if not return_obj: return_obj = self._binding_class() super(Indicator, self).to_obj(return_obj=return_obj, ns_info=ns_info) return_obj.negate = True if self.negate else None if self.confidence: return_obj.Confidence = self.confidence.to_obj(ns_info=ns_info) if self.indicator_types: return_obj.Type = self.indicator_types.to_obj(ns_info=ns_info) if self.indicated_ttps: return_obj.Indicated_TTP = self.indicated_ttps.to_obj( ns_info=ns_info) if self.producer: return_obj.Producer = self.producer.to_obj(ns_info=ns_info) if self.test_mechanisms: return_obj.Test_Mechanisms = self.test_mechanisms.to_obj( ns_info=ns_info) if self.likely_impact: return_obj.Likely_Impact = self.likely_impact.to_obj( ns_info=ns_info) if self.alternative_id: return_obj.Alternative_ID = self.alternative_id if self.valid_time_positions: return_obj.Valid_Time_Position = self.valid_time_positions.to_obj( ns_info=ns_info) if self.suggested_coas: return_obj.Suggested_COAs = self.suggested_coas.to_obj( ns_info=ns_info) if self.sightings: return_obj.Sightings = self.sightings.to_obj(ns_info=ns_info) if self.composite_indicator_expression: return_obj.Composite_Indicator_Expression = self.composite_indicator_expression.to_obj( ns_info=ns_info) if self.kill_chain_phases: return_obj.Kill_Chain_Phases = self.kill_chain_phases.to_obj( ns_info=ns_info) if self.related_indicators: return_obj.Related_Indicators = self.related_indicators.to_obj( ns_info=ns_info) if self.related_campaigns: return_obj.Related_Campaigns = self.related_campaigns.to_obj( ns_info=ns_info) if self.related_packages: return_obj.Related_Packages = self.related_packages.to_obj( ns_info=ns_info) if self.observables: if len(self.observables) > 1: root_observable = self._merge_observables(self.observables) else: root_observable = self.observables[0] return_obj.Observable = root_observable.to_obj(ns_info=ns_info) return return_obj @classmethod def from_obj(cls, obj, return_obj=None): if not obj: return None if not return_obj: return_obj = cls() super(Indicator, cls).from_obj(obj, return_obj=return_obj) if isinstance(obj, cls._binding_class): return_obj.negate = obj.negate return_obj.producer = InformationSource.from_obj(obj.Producer) return_obj.confidence = Confidence.from_obj(obj.Confidence) return_obj.sightings = Sightings.from_obj(obj.Sightings) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_obj( obj.Composite_Indicator_Expression) return_obj.kill_chain_phases = KillChainPhasesReference.from_obj( obj.Kill_Chain_Phases) return_obj.related_indicators = RelatedIndicators.from_obj( obj.Related_Indicators) return_obj.likely_impact = Statement.from_obj(obj.Likely_Impact) return_obj.indicator_types = IndicatorTypes.from_obj(obj.Type) return_obj.test_mechanisms = TestMechanisms.from_obj( obj.Test_Mechanisms) return_obj.suggested_coas = SuggestedCOAs.from_obj( obj.Suggested_COAs) return_obj.alternative_id = obj.Alternative_ID return_obj.indicated_ttps = _IndicatedTTPs.from_obj( obj.Indicated_TTP) return_obj.valid_time_positions = _ValidTimePositions.from_obj( obj.Valid_Time_Position) return_obj.observable = Observable.from_obj(obj.Observable) return_obj.related_campaigns = RelatedCampaignRefs.from_obj( obj.Related_Campaigns) return_obj.related_packages = RelatedPackageRefs.from_obj( obj.Related_Packages) return return_obj def to_dict(self): keys = ('observables', 'observable_composition_operator', 'negate') d = utils.to_dict(self, skip=keys) if self.negate: d['negate'] = True if self.observables: if len(self.observables) == 1: d['observable'] = self.observables[0].to_dict() else: composite_observable = self._merge_observables( self.observables) d['observable'] = composite_observable.to_dict() return d @classmethod def from_dict(cls, dict_repr, return_obj=None): if not dict_repr: return None if not return_obj: return_obj = cls() super(Indicator, cls).from_dict(dict_repr, return_obj=return_obj) get = dict_repr.get return_obj.negate = get('negate') return_obj.alternative_id = get('alternative_id') return_obj.indicated_ttps = _IndicatedTTPs.from_dict( get('indicated_ttps')) return_obj.test_mechanisms = TestMechanisms.from_list( get('test_mechanisms')) return_obj.suggested_coas = SuggestedCOAs.from_dict( get('suggested_coas')) return_obj.sightings = Sightings.from_dict(get('sightings')) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_dict( get('composite_indicator_expression')) return_obj.kill_chain_phases = KillChainPhasesReference.from_dict( get('kill_chain_phases')) return_obj.related_indicators = RelatedIndicators.from_dict( get('related_indicators')) return_obj.likely_impact = Statement.from_dict(get('likely_impact')) return_obj.indicator_types = IndicatorTypes.from_list( get('indicator_types')) return_obj.confidence = Confidence.from_dict(get('confidence')) return_obj.valid_time_positions = _ValidTimePositions.from_dict( get('valid_time_positions')) return_obj.observable = Observable.from_dict(get('observable')) return_obj.producer = InformationSource.from_dict(get('producer')) return_obj.related_campaigns = RelatedCampaignRefs.from_dict( get('related_campaigns')) return_obj.related_packages = RelatedPackageRefs.from_dict( get('related_packages')) return return_obj
class Indicator(stix.Entity): _binding = indicator_binding _binding_class = indicator_binding.IndicatorType _namespace = 'http://stix.mitre.org/Indicator-2' _version = "2.1.1" def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): self.id_ = id_ or stix.utils.create_id("indicator") self.idref = idref self.version = self._version self.producer = None self.observables = None self.title = title self.description = description self.short_description = short_description self.indicator_types = None self.confidence = None self.indicated_ttps = None self.test_mechanisms = None self.alternative_id = None self.suggested_coas = SuggestedCOAs() self.sightings = Sightings() self.composite_indicator_expression = None self.handling = None self.kill_chain_phases = KillChainPhasesReference() self.valid_time_positions = None self.related_indicators = None self.observable_composition_operator = "AND" if timestamp: self.timestamp = timestamp else: self.timestamp = datetime.now(tzutc()) if not idref else None @property def id_(self): return self._id @id_.setter def id_(self, value): if not value: self._id = None else: self._id = value self.idref = None @property def idref(self): return self._idref @idref.setter def idref(self, value): if not value: self._idref = None else: self._idref = value self.id_ = None # unset id_ if idref is present @property def timestamp(self): return self._timestamp @timestamp.setter def timestamp(self, value): self._timestamp = dates.parse_value(value) @property def description(self): return self._description @description.setter def description(self, value): if value: if isinstance(value, StructuredText): self._description = value else: self._description = StructuredText(value=value) else: self._description = None @property def short_description(self): return self._short_description @short_description.setter def short_description(self, value): if value: if isinstance(value, StructuredText): self._short_description = value else: self._short_description = StructuredText(value=value) else: self._short_description = None @property def producer(self): return self._producer @producer.setter def producer(self, value): if value and not isinstance(value, InformationSource): raise ValueError('value must be instance of InformationSource') self._producer = value @property def observable(self): if self.observables: return self.observables[0] else: return None @observable.setter def observable(self, observable): self._observables = [] self.add_observable(observable) @property def observables(self): return self._observables @observables.setter def observables(self, valuelist): self._observables = [] # initialize the variable if valuelist: for value in valuelist: self.add_observable(value) @property def alternative_id(self): return self._alternative_id @alternative_id.setter def alternative_id(self, value): self._alternative_id = [] if not value: return elif isinstance(value, list): for v in value: self.add_alternative_id(v) else: self.add_alternative_id(value) def add_alternative_id(self, value): if not value: return else: self.alternative_id.append(value) @property def valid_time_positions(self): return self._valid_time_positions @valid_time_positions.setter def valid_time_positions(self, value): self._valid_time_positions = [] if not value: return elif isinstance(value, list): for v in value: self.add_valid_time_position(v) else: self.add_valid_time_position(value) def add_valid_time_position(self, value): if not value: return elif isinstance(value, ValidTime): self.valid_time_positions.append(value) else: raise ValueError("value must be instance of ValidTime") @property def indicator_types(self): return self._indicator_types @indicator_types.setter def indicator_types(self, value): self._indicator_types = [] if not value: return elif isinstance(value, list): for v in value: self.add_indicator_type(v) else: self.add_indicator_type(value) def add_indicator_type(self, value): if not value: return elif isinstance(value, VocabString): self.indicator_types.append(value) else: tmp_indicator_type = IndicatorType(value=value) self.indicator_types.append(tmp_indicator_type) @property def confidence(self): return self._confidence @confidence.setter def confidence(self, value): if not value: self._confidence = None elif isinstance(value, Confidence): self._confidence = value else: self._confidence = Confidence(value=value) @property def indicated_ttps(self): return self._indicated_ttps @indicated_ttps.setter def indicated_ttps(self, value): self._indicated_ttps = [] if not value: return elif isinstance(value, list): for v in value: self.add_indicated_ttp(v) else: self.add_indicated_ttp(value) def add_indicated_ttp(self, v): if not v: return elif isinstance(v, RelatedTTP): self.indicated_ttps.append(v) else: self.indicated_ttps.append(RelatedTTP(v)) @property def test_mechanisms(self): return self._test_mechanisms @test_mechanisms.setter def test_mechanisms(self, value): self._test_mechanisms = [] if not value: return elif isinstance(value, list): for v in value: self.add_test_mechanism(v) else: self.add_test_mechanism(value) def add_test_mechanism(self, tm): if not tm: return elif isinstance(tm, _BaseTestMechanism): self.test_mechanisms.append(tm) else: raise ValueError('Cannot add type %s to test_mechanisms list' % type(tm)) @property def handling(self): return self._handling @handling.setter def handling(self, value): if not value: self._handling = None elif isinstance(value, Marking): self._handling = value else: raise ValueError('unable to set handling to type %s' % type(value)) @property def related_indicators(self): return self._related_indicators @related_indicators.setter def related_indicators(self, value): self._related_indicators = RelatedIndicators() if not value: return elif isinstance(value, RelatedIndicators): self._related_indicators = value elif isinstance(value, list): for v in value: self.add_related_indicator(v) else: self.add_related_indicator(value) def add_related_indicator(self, indicator): if not indicator: return elif isinstance(indicator, RelatedIndicator): self.related_indicators.append(indicator) else: self.related_indicators.append(RelatedIndicator(indicator)) @property def observable_composition_operator(self): return self._observable_composition_operator @observable_composition_operator.setter def observable_composition_operator(self, value): if value not in ("AND", "OR"): raise ValueError("observable_composition_operator must be 'AND' or 'OR'") self._observable_composition_operator = value def set_producer_identity(self, identity): ''' Sets the name of the producer of this indicator. The identity param can be a string (name) or an Identity instance. ''' if not self.producer: self.producer = InformationSource() if isinstance(identity, Identity): self.producer.identity = identity else: if not self.producer.identity: self.producer.identity = Identity() self.producer.identity.name = identity # assume it's a string def set_produced_time(self, produced_time): '''The produced date variable must be in ISO 8601 format''' if not self.producer.time: self.producer.time = Time() self.producer.time.produced_time = produced_time def get_produced_time(self): if self.producer and self.producer.time: return self.producer.time.produced_time else: return None def set_received_time(self, received_time): '''Set the time when this indicator was received''' if not self.producer.time: self.producer.time = Time() self.producer.time.received_time = received_time def get_received_time(self): '''Return the time when this indicator was received''' if self.producer and self.producer.time: return self.producer.time.received_time else: return None def add_observable(self, observable): ''' Adds an observable to the Indicator. If the number of observables associated with this indicator is greater than one, the indicator will nest all of its observables under a parent observable composition, with an logical operator of 'OR'. If this is not ideal, an separate indicator should be made for each observable''' if isinstance(observable, Observable): self.observables.append(observable) else: # try to cast it to an Observable type self.observables.append(Observable(observable)) def _merge_observables(self, observables): observable_composition = ObservableComposition() observable_composition.operator = self.observable_composition_operator for observable_ in observables: observable_composition.add(observable_) root_observable = Observable() root_observable.observable_composition = observable_composition return root_observable def add_object(self, object_): ''' The object paramter is wrapped in an observable and attached to the indicator. The object must be a cybox.core.DefinedObject instance''' observable = Observable(object_) self.add_observable(observable) def to_obj(self, return_obj=None): if not return_obj: return_obj = self._binding_class() return_obj.set_id(self.id_) return_obj.set_idref(self.idref) return_obj.set_timestamp(dates.serialize_value(self.timestamp)) return_obj.set_Title(self.title) if self.version: return_obj.set_version(self._version) if self.description: return_obj.set_Description(self.description.to_obj()) if self.short_description: return_obj.set_Short_Description(self.short_description.to_obj()) if self.confidence: return_obj.set_Confidence(self.confidence.to_obj()) if self.indicator_types: for indicator_type in self.indicator_types: tmp_indicator_type = indicator_type.to_obj() return_obj.add_Type(tmp_indicator_type) if self.indicated_ttps: return_obj.set_Indicated_TTP([x.to_obj() for x in self.indicated_ttps]) if self.observables: if len(self.observables) > 1: root_observable = self._merge_observables(self.observables) else: root_observable = self.observables[0] return_obj.set_Observable(root_observable.to_obj()) if self.producer: return_obj.set_Producer(self.producer.to_obj()) if self.test_mechanisms: tms_obj = self._binding.TestMechanismsType() tms_obj.set_Test_Mechanism([x.to_obj() for x in self.test_mechanisms]) return_obj.set_Test_Mechanisms(tms_obj) if self.alternative_id: return_obj.set_Alternative_ID(self.alternative_id) if self.valid_time_positions: return_obj.set_Valid_Time_Position([x.to_obj() for x in self.valid_time_positions]) if self.suggested_coas: return_obj.set_Suggested_COAs(self.suggested_coas.to_obj()) if self.sightings: return_obj.set_Sightings(self.sightings.to_obj()) if self.composite_indicator_expression: return_obj.set_Composite_Indicator_Expression(self.composite_indicator_expression.to_obj()) if self.handling: return_obj.set_Handling(self.handling.to_obj()) if self.kill_chain_phases: return_obj.set_Kill_Chain_Phases(self.kill_chain_phases.to_obj()) if self.related_indicators: return_obj.set_Related_Indicators(self.related_indicators.to_obj()) return return_obj @classmethod def from_obj(cls, obj, return_obj=None): if not obj: return None if not return_obj: return_obj = cls() return_obj.id_ = obj.get_id() return_obj.idref = obj.get_idref() return_obj.timestamp = obj.get_timestamp() if isinstance(obj, cls._binding_class): return_obj.title = obj.get_Title() return_obj.description = StructuredText.from_obj(obj.get_Description()) return_obj.short_description = StructuredText.from_obj(obj.get_Short_Description()) return_obj.producer = InformationSource.from_obj(obj.get_Producer()) return_obj.confidence = Confidence.from_obj(obj.get_Confidence()) return_obj.sightings = Sightings.from_obj(obj.get_Sightings()) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_obj(obj.get_Composite_Indicator_Expression()) return_obj.handling = Marking.from_obj(obj.get_Handling()) return_obj.kill_chain_phases = KillChainPhasesReference.from_obj(obj.get_Kill_Chain_Phases()) return_obj.related_indicators = RelatedIndicators.from_obj(obj.get_Related_Indicators()) if obj.get_version(): return_obj.version = obj.get_version() if obj.get_Type(): for indicator_type in obj.get_Type(): return_obj.add_indicator_type(VocabString.from_obj(indicator_type)) if obj.get_Observable(): observable_obj = obj.get_Observable() observable = Observable.from_obj(observable_obj) return_obj.observables.append(observable) if obj.get_Indicated_TTP(): return_obj.indicated_ttps = [RelatedTTP.from_obj(x) for x in obj.get_Indicated_TTP()] if obj.get_Test_Mechanisms(): return_obj.test_mechanisms = [_BaseTestMechanism.from_obj(x) for x in obj.get_Test_Mechanisms().get_Test_Mechanism()] if obj.get_Suggested_COAs(): return_obj.suggested_coas = SuggestedCOAs.from_obj(obj.get_Suggested_COAs()) if obj.get_Alternative_ID(): return_obj.alternative_id = obj.get_Alternative_ID() if obj.get_Valid_Time_Position(): return_obj.valid_time_positions = [ValidTime.from_obj(x) for x in obj.get_Valid_Time_Position()] return return_obj def to_dict(self): d = {} if self.id_: d['id'] = self.id_ if self.idref: d['idref'] = self.idref if self.timestamp: d['timestamp'] = dates.serialize_value(self.timestamp) if self.version: d['version'] = self.version if self.observables: if len(self.observables) == 1: d['observable'] = self.observables[0].to_dict() else: composite_observable = self._merge_observables(self.observables) d['observable'] = composite_observable.to_dict() if self.producer: d['producer'] = self.producer.to_dict() if self.title: d['title'] = self.title if self.description: d['description'] = self.description.to_dict() if self.short_description: d['short_description'] = self.short_description.to_dict() if self.indicator_types: d['indicator_types'] = [x.to_dict() for x in self.indicator_types] if self.confidence: d['confidence'] = self.confidence.to_dict() if self.indicated_ttps: d['indicated_ttps'] = [x.to_dict() for x in self.indicated_ttps] if self.test_mechanisms: d['test_mechanisms'] = [x.to_dict() for x in self.test_mechanisms] if self.alternative_id: d['alternative_id'] = self.alternative_id if self.valid_time_positions: d['valid_time_positions'] = [x.to_dict() for x in self.valid_time_positions] if self.suggested_coas: d['suggested_coas'] = self.suggested_coas.to_dict() if self.sightings: d['sightings'] = self.sightings.to_dict() if self.composite_indicator_expression: d['composite_indicator_expression'] = self.composite_indicator_expression.to_dict() if self.handling: d['handling'] = self.handling.to_dict() if self.kill_chain_phases: d['kill_chain_phases'] = self.kill_chain_phases.to_dict() if self.related_indicators: d['related_indicators'] = self.related_indicators.to_dict() return d @classmethod def from_dict(cls, dict_repr, return_obj=None): if not dict_repr: return None if not return_obj: return_obj = cls() return_obj.id_ = dict_repr.get('id') return_obj.idref = dict_repr.get('idref') return_obj.timestamp = dict_repr.get('timestamp') return_obj.title = dict_repr.get('title') return_obj.version = dict_repr.get('version', cls._version) observable_dict = dict_repr.get('observable') producer_dict = dict_repr.get('producer') description_dict = dict_repr.get('description') indicator_type_list = dict_repr.get('indicator_types', []) confidence_dict = dict_repr.get('confidence') alternative_id_dict = dict_repr.get('alternative_id') valid_time_position_dict = dict_repr.get('valid_time_positions') return_obj.short_description = StructuredText.from_dict(dict_repr.get('short_description')) return_obj.indicated_ttps = [RelatedTTP.from_dict(x) for x in dict_repr.get('indicated_ttps', [])] return_obj.test_mechanisms = [_BaseTestMechanism.from_dict(x) for x in dict_repr.get('test_mechanisms', [])] return_obj.suggested_coas = SuggestedCOAs.from_dict(dict_repr.get('suggested_coas')) return_obj.sightings = Sightings.from_dict(dict_repr.get('sightings')) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_dict(dict_repr.get('composite_indicator_expression')) return_obj.handling = Marking.from_dict(dict_repr.get('handling')) return_obj.kill_chain_phases = KillChainPhasesReference.from_dict(dict_repr.get('kill_chain_phases')) return_obj.related_indicators = RelatedIndicators.from_dict(dict_repr.get('related_indicators')) if observable_dict: return_obj.add_observable(Observable.from_dict(observable_dict)) if producer_dict: return_obj.producer = InformationSource.from_dict(producer_dict) if description_dict: return_obj.description = StructuredText.from_dict(description_dict) for indicator_type_dict in indicator_type_list: return_obj.add_indicator_type(VocabString.from_dict(indicator_type_dict)) if confidence_dict: return_obj.confidence = Confidence.from_dict(confidence_dict) if alternative_id_dict: return_obj.alternative_id = alternative_id_dict if valid_time_position_dict: for valid_time_position_type_dict in valid_time_position_dict: return_obj.add_valid_time_position(ValidTime.from_dict(valid_time_position_type_dict)) return return_obj
class Indicator(stix.Entity): _binding = indicator_binding _binding_class = indicator_binding.IndicatorType _namespace = 'http://stix.mitre.org/Indicator-2' _version = "2.1.1" def __init__(self, id_=None, idref=None, timestamp=None, title=None, description=None, short_description=None): self.id_ = id_ or stix.utils.create_id("indicator") self.idref = idref self.version = self._version self.producer = None self.observables = None self.title = title self.description = description self.short_description = short_description self.indicator_types = None self.confidence = None self.indicated_ttps = None self.test_mechanisms = None self.alternative_id = None self.suggested_coas = SuggestedCOAs() self.sightings = Sightings() self.composite_indicator_expression = None self.handling = None self.kill_chain_phases = KillChainPhasesReference() self.valid_time_positions = None self.related_indicators = None self.observable_composition_operator = "AND" self.likely_impact = None if timestamp: self.timestamp = timestamp else: self.timestamp = datetime.now(tzutc()) if not idref else None @property def id_(self): return self._id @id_.setter def id_(self, value): if not value: self._id = None else: self._id = value self.idref = None @property def idref(self): return self._idref @idref.setter def idref(self, value): if not value: self._idref = None else: self._idref = value self.id_ = None # unset id_ if idref is present @property def timestamp(self): return self._timestamp @timestamp.setter def timestamp(self, value): self._timestamp = dates.parse_value(value) @property def description(self): return self._description @description.setter def description(self, value): if value: if isinstance(value, StructuredText): self._description = value else: self._description = StructuredText(value=value) else: self._description = None @property def short_description(self): return self._short_description @short_description.setter def short_description(self, value): if value: if isinstance(value, StructuredText): self._short_description = value else: self._short_description = StructuredText(value=value) else: self._short_description = None @property def producer(self): return self._producer @producer.setter def producer(self, value): if value and not isinstance(value, InformationSource): raise ValueError('value must be instance of InformationSource') self._producer = value @property def observable(self): if self.observables: return self.observables[0] else: return None @observable.setter def observable(self, observable): self._observables = [] self.add_observable(observable) @property def observables(self): return self._observables @observables.setter def observables(self, valuelist): self._observables = [] # initialize the variable if valuelist: for value in valuelist: self.add_observable(value) @property def alternative_id(self): return self._alternative_id @alternative_id.setter def alternative_id(self, value): self._alternative_id = [] if not value: return elif isinstance(value, list): for v in value: self.add_alternative_id(v) else: self.add_alternative_id(value) def add_alternative_id(self, value): if not value: return else: self.alternative_id.append(value) @property def valid_time_positions(self): return self._valid_time_positions @valid_time_positions.setter def valid_time_positions(self, value): self._valid_time_positions = [] if not value: return elif isinstance(value, list): for v in value: self.add_valid_time_position(v) else: self.add_valid_time_position(value) def add_valid_time_position(self, value): if not value: return elif isinstance(value, ValidTime): self.valid_time_positions.append(value) else: raise ValueError("value must be instance of ValidTime") @property def indicator_types(self): return self._indicator_types @indicator_types.setter def indicator_types(self, value): self._indicator_types = IndicatorTypes() if not value: return elif isinstance(value, list): for v in value: self.add_indicator_type(v) else: self.add_indicator_type(value) def add_indicator_type(self, value): if not value: return elif isinstance(value, VocabString): self.indicator_types.append(value) else: tmp_indicator_type = IndicatorType(value=value) self.indicator_types.append(tmp_indicator_type) @property def confidence(self): return self._confidence @confidence.setter def confidence(self, value): if not value: self._confidence = None elif isinstance(value, Confidence): self._confidence = value else: self._confidence = Confidence(value=value) @property def indicated_ttps(self): return self._indicated_ttps @indicated_ttps.setter def indicated_ttps(self, value): self._indicated_ttps = [] if not value: return elif isinstance(value, list): for v in value: self.add_indicated_ttp(v) else: self.add_indicated_ttp(value) def add_indicated_ttp(self, v): if not v: return elif isinstance(v, RelatedTTP): self.indicated_ttps.append(v) else: self.indicated_ttps.append(RelatedTTP(v)) @property def test_mechanisms(self): return self._test_mechanisms @test_mechanisms.setter def test_mechanisms(self, value): self._test_mechanisms = [] if not value: return elif isinstance(value, list): for v in value: self.add_test_mechanism(v) else: self.add_test_mechanism(value) def add_test_mechanism(self, tm): if not tm: return elif isinstance(tm, _BaseTestMechanism): self.test_mechanisms.append(tm) else: raise ValueError('Cannot add type %s to test_mechanisms list' % type(tm)) @property def handling(self): return self._handling @handling.setter def handling(self, value): if not value: self._handling = None elif isinstance(value, Marking): self._handling = value else: raise ValueError('unable to set handling to type %s' % type(value)) @property def related_indicators(self): return self._related_indicators @related_indicators.setter def related_indicators(self, value): self._related_indicators = RelatedIndicators() if not value: return elif isinstance(value, RelatedIndicators): self._related_indicators = value elif isinstance(value, list): for v in value: self.add_related_indicator(v) else: self.add_related_indicator(value) def add_related_indicator(self, indicator): if not indicator: return elif isinstance(indicator, RelatedIndicator): self.related_indicators.append(indicator) else: self.related_indicators.append(RelatedIndicator(indicator)) @property def observable_composition_operator(self): return self._observable_composition_operator @observable_composition_operator.setter def observable_composition_operator(self, value): if value not in ("AND", "OR"): raise ValueError("observable_composition_operator must be 'AND' or 'OR'") self._observable_composition_operator = value @property def likely_impact(self): return self._likely_impact @likely_impact.setter def likely_impact(self, value): if not value: self._likely_impact = None elif isinstance(value, Statement): self._likely_impact = value else: self._likely_impact = Statement(value=value) def set_producer_identity(self, identity): ''' Sets the name of the producer of this indicator. The identity param can be a string (name) or an Identity instance. ''' if not self.producer: self.producer = InformationSource() if isinstance(identity, Identity): self.producer.identity = identity else: if not self.producer.identity: self.producer.identity = Identity() self.producer.identity.name = identity # assume it's a string def set_produced_time(self, produced_time): '''The produced date variable must be in ISO 8601 format''' if not self.producer.time: self.producer.time = Time() self.producer.time.produced_time = produced_time def get_produced_time(self): if self.producer and self.producer.time: return self.producer.time.produced_time else: return None def set_received_time(self, received_time): '''Set the time when this indicator was received''' if not self.producer.time: self.producer.time = Time() self.producer.time.received_time = received_time def get_received_time(self): '''Return the time when this indicator was received''' if self.producer and self.producer.time: return self.producer.time.received_time else: return None def add_observable(self, observable): ''' Adds an observable to the Indicator. If the number of observables associated with this indicator is greater than one, the indicator will nest all of its observables under a parent observable composition, with an logical operator of 'OR'. If this is not ideal, an separate indicator should be made for each observable''' if isinstance(observable, Observable): self.observables.append(observable) else: # try to cast it to an Observable type self.observables.append(Observable(observable)) def _merge_observables(self, observables): observable_composition = ObservableComposition() observable_composition.operator = self.observable_composition_operator for observable_ in observables: observable_composition.add(observable_) root_observable = Observable() root_observable.observable_composition = observable_composition return root_observable def add_object(self, object_): ''' The object paramter is wrapped in an observable and attached to the indicator. The object must be a cybox.core.DefinedObject instance''' observable = Observable(object_) self.add_observable(observable) def to_obj(self, return_obj=None): if not return_obj: return_obj = self._binding_class() return_obj.set_id(self.id_) return_obj.set_idref(self.idref) return_obj.set_timestamp(dates.serialize_value(self.timestamp)) return_obj.set_Title(self.title) if self.version: return_obj.set_version(self._version) if self.description: return_obj.set_Description(self.description.to_obj()) if self.short_description: return_obj.set_Short_Description(self.short_description.to_obj()) if self.confidence: return_obj.set_Confidence(self.confidence.to_obj()) if self.indicator_types: for indicator_type in self.indicator_types: tmp_indicator_type = indicator_type.to_obj() return_obj.add_Type(tmp_indicator_type) if self.indicated_ttps: return_obj.set_Indicated_TTP([x.to_obj() for x in self.indicated_ttps]) if self.observables: if len(self.observables) > 1: root_observable = self._merge_observables(self.observables) else: root_observable = self.observables[0] return_obj.set_Observable(root_observable.to_obj()) if self.producer: return_obj.set_Producer(self.producer.to_obj()) if self.test_mechanisms: tms_obj = self._binding.TestMechanismsType() tms_obj.set_Test_Mechanism([x.to_obj() for x in self.test_mechanisms]) return_obj.set_Test_Mechanisms(tms_obj) if self.likely_impact: return_obj.set_Likely_Impact(self.likely_impact.to_obj()) if self.alternative_id: return_obj.set_Alternative_ID(self.alternative_id) if self.valid_time_positions: return_obj.set_Valid_Time_Position([x.to_obj() for x in self.valid_time_positions]) if self.suggested_coas: return_obj.set_Suggested_COAs(self.suggested_coas.to_obj()) if self.sightings: return_obj.set_Sightings(self.sightings.to_obj()) if self.composite_indicator_expression: return_obj.set_Composite_Indicator_Expression(self.composite_indicator_expression.to_obj()) if self.handling: return_obj.set_Handling(self.handling.to_obj()) if self.kill_chain_phases: return_obj.set_Kill_Chain_Phases(self.kill_chain_phases.to_obj()) if self.related_indicators: return_obj.set_Related_Indicators(self.related_indicators.to_obj()) return return_obj @classmethod def from_obj(cls, obj, return_obj=None): if not obj: return None if not return_obj: return_obj = cls() return_obj.id_ = obj.get_id() return_obj.idref = obj.get_idref() return_obj.timestamp = obj.get_timestamp() if isinstance(obj, cls._binding_class): return_obj.title = obj.get_Title() return_obj.description = StructuredText.from_obj(obj.get_Description()) return_obj.short_description = StructuredText.from_obj(obj.get_Short_Description()) return_obj.producer = InformationSource.from_obj(obj.get_Producer()) return_obj.confidence = Confidence.from_obj(obj.get_Confidence()) return_obj.sightings = Sightings.from_obj(obj.get_Sightings()) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_obj(obj.get_Composite_Indicator_Expression()) return_obj.handling = Marking.from_obj(obj.get_Handling()) return_obj.kill_chain_phases = KillChainPhasesReference.from_obj(obj.get_Kill_Chain_Phases()) return_obj.related_indicators = RelatedIndicators.from_obj(obj.get_Related_Indicators()) return_obj.likely_impact = Statement.from_obj(obj.get_Likely_Impact()) if obj.get_version(): return_obj.version = obj.get_version() if obj.get_Type(): for indicator_type in obj.get_Type(): return_obj.add_indicator_type(VocabString.from_obj(indicator_type)) if obj.get_Observable(): observable_obj = obj.get_Observable() observable = Observable.from_obj(observable_obj) return_obj.observables.append(observable) if obj.get_Indicated_TTP(): return_obj.indicated_ttps = [RelatedTTP.from_obj(x) for x in obj.get_Indicated_TTP()] if obj.get_Test_Mechanisms(): return_obj.test_mechanisms = [_BaseTestMechanism.from_obj(x) for x in obj.get_Test_Mechanisms().get_Test_Mechanism()] if obj.get_Suggested_COAs(): return_obj.suggested_coas = SuggestedCOAs.from_obj(obj.get_Suggested_COAs()) if obj.get_Alternative_ID(): return_obj.alternative_id = obj.get_Alternative_ID() if obj.get_Valid_Time_Position(): return_obj.valid_time_positions = [ValidTime.from_obj(x) for x in obj.get_Valid_Time_Position()] return return_obj def to_dict(self): d = {} if self.id_: d['id'] = self.id_ if self.idref: d['idref'] = self.idref if self.timestamp: d['timestamp'] = dates.serialize_value(self.timestamp) if self.version: d['version'] = self.version if self.observables: if len(self.observables) == 1: d['observable'] = self.observables[0].to_dict() else: composite_observable = self._merge_observables(self.observables) d['observable'] = composite_observable.to_dict() if self.producer: d['producer'] = self.producer.to_dict() if self.title: d['title'] = self.title if self.description: d['description'] = self.description.to_dict() if self.short_description: d['short_description'] = self.short_description.to_dict() if self.indicator_types: d['indicator_types'] = [x.to_dict() for x in self.indicator_types] if self.confidence: d['confidence'] = self.confidence.to_dict() if self.indicated_ttps: d['indicated_ttps'] = [x.to_dict() for x in self.indicated_ttps] if self.test_mechanisms: d['test_mechanisms'] = [x.to_dict() for x in self.test_mechanisms] if self.likely_impact: d['likely_impact'] = self.likely_impact.to_dict() if self.alternative_id: d['alternative_id'] = self.alternative_id if self.valid_time_positions: d['valid_time_positions'] = [x.to_dict() for x in self.valid_time_positions] if self.suggested_coas: d['suggested_coas'] = self.suggested_coas.to_dict() if self.sightings: d['sightings'] = self.sightings.to_dict() if self.composite_indicator_expression: d['composite_indicator_expression'] = self.composite_indicator_expression.to_dict() if self.handling: d['handling'] = self.handling.to_dict() if self.kill_chain_phases: d['kill_chain_phases'] = self.kill_chain_phases.to_dict() if self.related_indicators: d['related_indicators'] = self.related_indicators.to_dict() return d @classmethod def from_dict(cls, dict_repr, return_obj=None): if not dict_repr: return None if not return_obj: return_obj = cls() return_obj.id_ = dict_repr.get('id') return_obj.idref = dict_repr.get('idref') return_obj.timestamp = dict_repr.get('timestamp') return_obj.title = dict_repr.get('title') return_obj.version = dict_repr.get('version', cls._version) observable_dict = dict_repr.get('observable') producer_dict = dict_repr.get('producer') description_dict = dict_repr.get('description') indicator_type_list = dict_repr.get('indicator_types', []) confidence_dict = dict_repr.get('confidence') alternative_id_dict = dict_repr.get('alternative_id') valid_time_position_dict = dict_repr.get('valid_time_positions') return_obj.short_description = StructuredText.from_dict(dict_repr.get('short_description')) return_obj.indicated_ttps = [RelatedTTP.from_dict(x) for x in dict_repr.get('indicated_ttps', [])] return_obj.test_mechanisms = [_BaseTestMechanism.from_dict(x) for x in dict_repr.get('test_mechanisms', [])] return_obj.suggested_coas = SuggestedCOAs.from_dict(dict_repr.get('suggested_coas')) return_obj.sightings = Sightings.from_dict(dict_repr.get('sightings')) return_obj.composite_indicator_expression = CompositeIndicatorExpression.from_dict(dict_repr.get('composite_indicator_expression')) return_obj.handling = Marking.from_dict(dict_repr.get('handling')) return_obj.kill_chain_phases = KillChainPhasesReference.from_dict(dict_repr.get('kill_chain_phases')) return_obj.related_indicators = RelatedIndicators.from_dict(dict_repr.get('related_indicators')) return_obj.likely_impact = Statement.from_dict(dict_repr.get('likely_impact')) if observable_dict: return_obj.add_observable(Observable.from_dict(observable_dict)) if producer_dict: return_obj.producer = InformationSource.from_dict(producer_dict) if description_dict: return_obj.description = StructuredText.from_dict(description_dict) for indicator_type_dict in indicator_type_list: return_obj.add_indicator_type(VocabString.from_dict(indicator_type_dict)) if confidence_dict: return_obj.confidence = Confidence.from_dict(confidence_dict) if alternative_id_dict: return_obj.alternative_id = alternative_id_dict if valid_time_position_dict: for valid_time_position_type_dict in valid_time_position_dict: return_obj.add_valid_time_position(ValidTime.from_dict(valid_time_position_type_dict)) return return_obj