From 5577686ee8b71bc72c568c64b193494da8b87672 Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Fri, 6 Oct 2017 15:09:14 -0400 Subject: [PATCH 1/4] Add new STIX2.1 SDOs and additional properties --- stix2/__init__.py | 5 +- stix2/common.py | 10 +++- stix2/core.py | 7 ++- stix2/sdo.py | 118 ++++++++++++++++++++++++++++++++++++++++++++-- stix2/sro.py | 5 ++ 5 files changed, 137 insertions(+), 8 deletions(-) diff --git a/stix2/__init__.py b/stix2/__init__.py index 53c2fb1..9361ad9 100644 --- a/stix2/__init__.py +++ b/stix2/__init__.py @@ -42,8 +42,9 @@ from .patterns import (AndBooleanExpression, AndObservationExpression, StartStopQualifier, StringConstant, TimestampConstant, WithinQualifier) from .sdo import (AttackPattern, Campaign, CourseOfAction, CustomObject, - Identity, Indicator, IntrusionSet, Malware, ObservedData, - Report, ThreatActor, Tool, Vulnerability) + Identity, Indicator, IntrusionSet, Location, Malware, Note, + ObservedData, Opinion, Report, ThreatActor, Tool, + Vulnerability) from .sources import CompositeDataSource from .sources.filesystem import (FileSystemSink, FileSystemSource, FileSystemStore) diff --git a/stix2/common.py b/stix2/common.py index d7994c6..8037657 100644 --- a/stix2/common.py +++ b/stix2/common.py @@ -11,6 +11,7 @@ from .utils import NOW, get_dict class ExternalReference(_STIXBase): + _properties = OrderedDict() _properties.update([ ('source_name', StringProperty(required=True)), @@ -26,6 +27,7 @@ class ExternalReference(_STIXBase): class KillChainPhase(_STIXBase): + _properties = OrderedDict() _properties.update([ ('kill_chain_name', StringProperty(required=True)), @@ -34,6 +36,7 @@ class KillChainPhase(_STIXBase): class GranularMarking(_STIXBase): + _properties = OrderedDict() _properties.update([ ('marking_ref', ReferenceProperty(required=True, type="marking-definition")), @@ -42,7 +45,7 @@ class GranularMarking(_STIXBase): class TLPMarking(_STIXBase): - # TODO: don't allow the creation of any other TLPMarkings than the ones below + _type = 'tlp' _properties = OrderedDict() _properties.update([ @@ -51,6 +54,7 @@ class TLPMarking(_STIXBase): class StatementMarking(_STIXBase): + _type = 'statement' _properties = OrderedDict() _properties.update([ @@ -78,6 +82,7 @@ class MarkingProperty(Property): class MarkingDefinition(_STIXBase, MarkingsMixin): + _type = 'marking-definition' _properties = OrderedDict() _properties.update([ @@ -137,6 +142,7 @@ def CustomMarking(type='x-custom-marking', properties=None): def custom_builder(cls): class _Custom(cls, _STIXBase): + _type = type _properties = OrderedDict() @@ -155,6 +161,8 @@ def CustomMarking(type='x-custom-marking', properties=None): return custom_builder +# TODO: don't allow the creation of any other TLPMarkings than the ones below + TLP_WHITE = MarkingDefinition( id="marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9", created="2017-01-20T00:00:00.000Z", diff --git a/stix2/core.py b/stix2/core.py index 0271e34..38c9f48 100644 --- a/stix2/core.py +++ b/stix2/core.py @@ -7,8 +7,8 @@ from .base import _STIXBase from .common import MarkingDefinition from .properties import IDProperty, ListProperty, Property, TypeProperty from .sdo import (AttackPattern, Campaign, CourseOfAction, Identity, Indicator, - IntrusionSet, Malware, ObservedData, Report, ThreatActor, - Tool, Vulnerability) + IntrusionSet, Location, Malware, Note, ObservedData, Opinion, + Report, ThreatActor, Tool, Vulnerability) from .sro import Relationship, Sighting from .utils import get_dict @@ -59,9 +59,12 @@ OBJ_MAP = { 'identity': Identity, 'indicator': Indicator, 'intrusion-set': IntrusionSet, + 'location': Location, 'malware': Malware, + 'note': Note, 'marking-definition': MarkingDefinition, 'observed-data': ObservedData, + 'opinion': Opinion, 'report': Report, 'relationship': Relationship, 'threat-actor': ThreatActor, diff --git a/stix2/sdo.py b/stix2/sdo.py index 4664d99..5710426 100644 --- a/stix2/sdo.py +++ b/stix2/sdo.py @@ -8,9 +8,10 @@ from .base import _STIXBase from .common import ExternalReference, GranularMarking, KillChainPhase from .markings import MarkingsMixin from .observables import ObservableProperty -from .properties import (BooleanProperty, IDProperty, IntegerProperty, - ListProperty, PatternProperty, ReferenceProperty, - StringProperty, TimestampProperty, TypeProperty) +from .properties import (BooleanProperty, EnumProperty, FloatProperty, + IDProperty, IntegerProperty, ListProperty, + PatternProperty, ReferenceProperty, StringProperty, + TimestampProperty, TypeProperty) from .utils import NOW @@ -33,6 +34,8 @@ class AttackPattern(STIXDomainObject): ('kill_chain_phases', ListProperty(KillChainPhase)), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -57,6 +60,8 @@ class Campaign(STIXDomainObject): ('objective', StringProperty()), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -77,6 +82,8 @@ class CourseOfAction(STIXDomainObject): ('description', StringProperty()), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -100,6 +107,8 @@ class Identity(STIXDomainObject): ('contact_information', StringProperty()), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -124,6 +133,8 @@ class Indicator(STIXDomainObject): ('kill_chain_phases', ListProperty(KillChainPhase)), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty, required=True)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -151,6 +162,38 @@ class IntrusionSet(STIXDomainObject): ('secondary_motivations', ListProperty(StringProperty)), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), + ('external_references', ListProperty(ExternalReference)), + ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), + ('granular_markings', ListProperty(GranularMarking)), + ]) + + +class Location(STIXDomainObject): + + _type = 'location' + _properties = OrderedDict() + _properties.update([ + ('type', TypeProperty(_type)), + ('id', IDProperty(_type)), + ('created_by_ref', ReferenceProperty(type="identity")), + ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')), + ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), + ('description', StringProperty()), + ('latitude', FloatProperty()), + ('longitude', FloatProperty()), + ('precision', FloatProperty()), + ('region', StringProperty()), + ('country', StringProperty()), + ('administrative_area', StringProperty()), + ('city', StringProperty()), + ('street_address', StringProperty()), + ('postal_code', StringProperty()), + ('revoked', BooleanProperty()), + ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -172,6 +215,32 @@ class Malware(STIXDomainObject): ('kill_chain_phases', ListProperty(KillChainPhase)), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty, required=True)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), + ('external_references', ListProperty(ExternalReference)), + ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), + ('granular_markings', ListProperty(GranularMarking)), + ]) + + +class Note(STIXDomainObject): + + _type = 'note' + _properties = OrderedDict() + _properties.update([ + ('type', TypeProperty(_type)), + ('id', IDProperty(_type)), + ('created_by_ref', ReferenceProperty(type="identity")), + ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')), + ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), + ('summary', StringProperty()), + ('description', StringProperty(required=True)), + ('authors', ListProperty(StringProperty)), + ('object_refs', ListProperty(ReferenceProperty, required=True)), + ('revoked', BooleanProperty()), + ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -194,6 +263,38 @@ class ObservedData(STIXDomainObject): ('objects', ObservableProperty(required=True)), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), + ('external_references', ListProperty(ExternalReference)), + ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), + ('granular_markings', ListProperty(GranularMarking)), + ]) + + +class Opinion(STIXDomainObject): + + _type = 'opinion' + _properties = OrderedDict() + _properties.update([ + ('type', TypeProperty(_type)), + ('id', IDProperty(_type)), + ('created_by_ref', ReferenceProperty(type="identity")), + ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')), + ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), + ('description', StringProperty), + ('authors', ListProperty(StringProperty)), + ('object_refs', ListProperty(ReferenceProperty, required=True)), + ('opinion', EnumProperty(allowed=[ + 'strongly-disagree', + 'disagree', + 'neutral', + 'agree', + 'strongly-agree' + ], required=True)), + ('revoked', BooleanProperty()), + ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -216,6 +317,8 @@ class Report(STIXDomainObject): ('object_refs', ListProperty(ReferenceProperty, required=True)), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty, required=True)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -244,6 +347,8 @@ class ThreatActor(STIXDomainObject): ('personal_motivations', ListProperty(StringProperty)), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty, required=True)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -266,6 +371,8 @@ class Tool(STIXDomainObject): ('tool_version', StringProperty()), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty, required=True)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -286,6 +393,8 @@ class Vulnerability(STIXDomainObject): ('description', StringProperty()), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -322,6 +431,7 @@ def CustomObject(type='x-custom-type', properties=None): def custom_builder(cls): class _Custom(cls, STIXDomainObject): + _type = type _properties = OrderedDict() _properties.update([ @@ -341,6 +451,8 @@ def CustomObject(type='x-custom-type', properties=None): _properties.update([ ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), diff --git a/stix2/sro.py b/stix2/sro.py index 4fa0465..5e75aae 100644 --- a/stix2/sro.py +++ b/stix2/sro.py @@ -31,6 +31,8 @@ class Relationship(STIXRelationshipObject): ('target_ref', ReferenceProperty(required=True)), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), @@ -51,6 +53,7 @@ class Relationship(STIXRelationshipObject): class Sighting(STIXRelationshipObject): + _type = 'sighting' _properties = OrderedDict() _properties.update([ @@ -68,6 +71,8 @@ class Sighting(STIXRelationshipObject): ('summary', BooleanProperty()), ('revoked', BooleanProperty()), ('labels', ListProperty(StringProperty)), + ('confidence', IntegerProperty()), + ('lang', StringProperty()), ('external_references', ListProperty(ExternalReference)), ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), ('granular_markings', ListProperty(GranularMarking)), From 2ec8205f1e58ee271afad0aa7677262248181fe6 Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Mon, 9 Oct 2017 07:22:19 -0400 Subject: [PATCH 2/4] Implement confidence conversion scales --- stix2/confidence/__init__.py | 3 + stix2/confidence/scales.py | 448 +++++++++++++++++++++++++++++++++++ 2 files changed, 451 insertions(+) create mode 100644 stix2/confidence/__init__.py create mode 100644 stix2/confidence/scales.py diff --git a/stix2/confidence/__init__.py b/stix2/confidence/__init__.py new file mode 100644 index 0000000..4bae011 --- /dev/null +++ b/stix2/confidence/__init__.py @@ -0,0 +1,3 @@ +""" +Functions to operate with STIX 2 Confidence scales. +""" diff --git a/stix2/confidence/scales.py b/stix2/confidence/scales.py new file mode 100644 index 0000000..6ee1d64 --- /dev/null +++ b/stix2/confidence/scales.py @@ -0,0 +1,448 @@ +"""Functions to perform conversions between the different Confidence scales. +As specified in STIX™ Version 2.1. Part 1: STIX Core Concepts - Appendix B""" + + +def none_low_med_high_to_value(scale_value): + """ + This method will transform a string value from the None / Low / Med / + High scale to its confidence integer representation. + + Notes: + The scale for this confidence representation is the following. + "None" -> 0 + "Low" -> 15 + "Med" -> 50 + "High" -> 85 + + Args: + scale_value: A string value from the scale. Accepted strings are + "None", "Low", "Med" and "High". Argument is case sensitive. + + Returns: + int: The numerical representation corresponding to values in the None / + Low / Med / High scale. + + Raises: + ValueError: If `scale_value` is not within the accepted strings. + """ + if scale_value == "None": + return 0 + elif scale_value == "Low": + return 15 + elif scale_value == "Med": + return 50 + elif scale_value == "High": + return 85 + else: + raise ValueError("STIX Confidence value cannot be determined for %s" % scale_value) + + +def value_to_none_low_medium_high(confidence_value): + """ + This method will transform an integer value into the None / Low / Med / + High scale string representation. + + Notes: + The scale for this confidence representation is the following. + 0 -> "None" + 1-29 -> "Low" + 30-69 -> "Med" + 70-100 -> "High" + + Args: + confidence_value: An integer value between 0 and 100. + + Returns: + str: A string corresponding to the None / Low / Med / High scale. + + Raises: + ValueError: If `confidence_value` is out of bounds. + + """ + if confidence_value == 0: + return "None" + elif 29 >= confidence_value >= 1: + return "Low" + elif 69 >= confidence_value >= 30: + return "Med" + elif 100 >= confidence_value >= 70: + return "High" + else: + raise ValueError("Range of values out of bounds: %s" % confidence_value) + + +def zero_ten_to_value(scale_value): + """ + This method will transform a string value from the 0-10 scale to its + confidence integer representation. + + Notes: + The scale for this confidence representation is the following. + "0" -> 0 + "1" -> 10 + "2" -> 20 + "3" -> 30 + "4" -> 40 + "5" -> 50 + "6" -> 60 + "7" -> 70 + "8" -> 80 + "9" -> 90 + "10" -> 100 + + Args: + scale_value: A string value from the scale. Accepted strings are "0" + through "10" inclusive. + + Returns: + int: The numerical representation corresponding to values in the 0-10 + scale. + + Raises: + ValueError: If `scale_value` is not within the accepted strings. + + """ + if scale_value == "0": + return 0 + elif scale_value == "1": + return 10 + elif scale_value == "2": + return 20 + elif scale_value == "3": + return 30 + elif scale_value == "4": + return 40 + elif scale_value == "5": + return 50 + elif scale_value == "6": + return 60 + elif scale_value == "7": + return 70 + elif scale_value == "8": + return 80 + elif scale_value == "9": + return 90 + elif scale_value == "10": + return 100 + else: + raise ValueError("STIX Confidence value cannot be determined for %s" % scale_value) + + +def value_to_zero_ten(confidence_value): + """ + This method will transform an integer value into the 0-10 scale string + representation. + + Notes: + The scale for this confidence representation is the following. + 0-4 -> "0" + 5-14 -> "1" + 15-24 -> "2" + 25-34 -> "3" + 35-44 -> "4" + 45-54 -> "5" + 55-64 -> "6" + 65-74 -> "7" + 75-84 -> "8" + 85-94 -> "9" + 95-100 -> "10" + + Args: + confidence_value: An integer value between 0 and 100. + + Returns: + str: A string corresponding to the 0-10 scale. + + Raises: + ValueError: If `confidence_value` is out of bounds. + + """ + if 4 >= confidence_value >= 0: + return "0" + elif 14 >= confidence_value >= 5: + return "1" + elif 24 >= confidence_value >= 15: + return "2" + elif 34 >= confidence_value >= 25: + return "3" + elif 44 >= confidence_value >= 35: + return "4" + elif 54 >= confidence_value >= 45: + return "5" + elif 64 >= confidence_value >= 55: + return "6" + elif 74 >= confidence_value >= 65: + return "7" + elif 84 >= confidence_value >= 75: + return "8" + elif 94 >= confidence_value >= 85: + return "9" + elif 100 >= confidence_value >= 95: + return "10" + else: + raise ValueError("Range of values out of bounds: %s" % confidence_value) + + +def admiralty_credibility_to_value(scale_value): + """ + This method will transform a string value from the Admiralty Credibility + scale to its confidence integer representation. + + Notes: + The scale for this confidence representation is the following. + "6 - Truth cannot be judged" -> N/A + "5 - Improbable" -> 10 + "4 - Doubtful" -> 30 + "3 - Possibly True" -> 50 + "2 - Probably True" -> 70 + "1 - Confirmed by other sources" -> 90 + + Args: + scale_value: A string value from the scale. Accepted strings are + "6 - Truth cannot be judged", "5 - Improbable", "4 - Doubtful", + "3 - Possibly True", "2 - Probably True" and + "1 - Confirmed by other sources". Argument is case sensitive. + + Returns: + int: The numerical representation corresponding to values in the + Admiralty Credibility scale. + + Raises: + ValueError: If `scale_value` is not within the accepted strings. + + """ + if scale_value == "6 - Truth cannot be judged": + pass # TODO: Ask what happens here! + elif scale_value == "5 - Improbable": + return 10 + elif scale_value == "4 - Doubtful": + return 30 + elif scale_value == "3 - Possibly True": + return 50 + elif scale_value == "2 - Probably True": + return 70 + elif scale_value == "1 - Confirmed by other sources": + return 90 + else: + raise ValueError("STIX Confidence value cannot be determined for %s" % scale_value) + + +def value_to_admiralty_credibility(confidence_value): + """ + This method will transform an integer value into the Admiralty Credibility + scale string representation. + + Notes: + The scale for this confidence representation is the following. + N/A -> "6 - Truth cannot be judged" + 0-19 -> "5 - Improbable" + 20-39 -> "4 - Doubtful" + 40-59 -> "3 - Possibly True" + 60-79 -> "2 - Probably True" + 80-100 -> "1 - Confirmed by other sources" + + Args: + confidence_value: An integer value between 0 and 100. + + Returns: + str: A string corresponding to the Admiralty Credibility scale. + + Raises: + ValueError: If `confidence_value` is out of bounds. + + """ + # TODO: Ask what happens with "6 - Truth cannot be judged" ! + if 19 >= confidence_value >= 0: + return "5 - Improbable" + elif 39 >= confidence_value >= 20: + return "4 - Doubtful" + elif 59 >= confidence_value >= 40: + return "3 - Possibly True" + elif 79 >= confidence_value >= 60: + return "2 - Probably True" + elif 100 >= confidence_value >= 80: + return "1 - Confirmed by other sources" + else: + raise ValueError("Range of values out of bounds: %s" % confidence_value) + + +def wep_to_value(scale_value): + """ + This method will transform a string value from the WEP scale to its + confidence integer representation. + + Notes: + The scale for this confidence representation is the following. + "Impossible" -> 0 + "Highly Unlikely/Almost Certainly Not" -> 10 + "Unlikely/Probably Not" -> 20 + "Even Chance" -> 50 + "Likely/Probable" -> 70 + "Highly likely/Almost Certain" -> 90 + "Certain" -> 100 + + Args: + scale_value: A string value from the scale. Accepted strings are + "Impossible", "Highly Unlikely/Almost Certainly Not", + "Unlikely/Probably Not", "Even Chance", "Likely/Probable", + "Highly likely/Almost Certain" and "Certain". Argument is case + sensitive. + + Returns: + int: The numerical representation corresponding to values in the WEP + scale. + + Raises: + ValueError: If `scale_value` is not within the accepted strings. + + """ + if scale_value == "Impossible": + return 0 + elif scale_value == "Highly Unlikely/Almost Certainly Not": + return 10 + elif scale_value == "Unlikely/Probably Not": + return 30 + elif scale_value == "Even Chance": + return 50 + elif scale_value == "Likely/Probable": + return 70 + elif scale_value == "Highly likely/Almost Certain": + return 90 + elif scale_value == "Certain": + return 100 + else: + raise ValueError("STIX Confidence value cannot be determined for %s" % scale_value) + + +def value_to_wep(confidence_value): + """ + This method will transform an integer value into the WEP scale string + representation. + + Notes: + The scale for this confidence representation is the following. + 0 -> "Impossible" + 1-19 -> "Highly Unlikely/Almost Certainly Not" + 20-39 -> "Unlikely/Probably Not" + 40-59 -> "Even Chance" + 60-79 -> "Likely/Probable" + 80-99 -> "Highly likely/Almost Certain" + 100 -> "Certain" + + Args: + confidence_value: An integer value between 0 and 100. + + Returns: + str: A string corresponding to the WEP scale. + + Raises: + ValueError: If `confidence_value` is out of bounds. + + """ + if confidence_value == 0: + return "Impossible" + elif 19 >= confidence_value >= 1: + return "Highly Unlikely/Almost Certainly Not" + elif 39 >= confidence_value >= 20: + return "Unlikely/Probably Not" + elif 59 >= confidence_value >= 40: + return "Even Chance" + elif 79 >= confidence_value >= 60: + return "Likely/Probable" + elif 99 >= confidence_value >= 80: + return "Highly likely/Almost Certain" + elif confidence_value == 100: + return "Certain" + else: + raise ValueError("Range of values out of bounds: %s" % confidence_value) + + +def dni_to_value(scale_value): + """ + This method will transform a string value from the DNI scale to its + confidence integer representation. + + Notes: + The scale for this confidence representation is the following. + "Almost No Chance / Remote" -> 5 + "Very Unlikely / Highly Improbable" -> 15 + "Unlikely / Improbable" -> 30 + "Roughly Even Change / Roughly Even Odds" -> 50 + "Likely / Probable" -> 70 + "Very Likely / Highly Probable" -> 85 + "Almost Certain / Nearly Certain" -> 95 + + Args: + scale_value: A string value from the scale. Accepted strings are + "Almost No Chance / Remote", "Very Unlikely / Highly Improbable", + "Unlikely / Improbable", "Roughly Even Change / Roughly Even Odds", + "Likely / Probable", "Very Likely / Highly Probable" and + "Almost Certain / Nearly Certain". Argument is case sensitive. + + Returns: + int: The numerical representation corresponding to values in the DNI + scale. + + Raises: + ValueError: If `scale_value` is not within the accepted strings. + + """ + if scale_value == "Almost No Chance / Remote": + return 5 + elif scale_value == "Very Unlikely / Highly Improbable": + return 15 + elif scale_value == "Unlikely / Improbable": + return 30 + elif scale_value == "Roughly Even Change / Roughly Even Odds": + return 50 + elif scale_value == "Likely / Probable": + return 70 + elif scale_value == "Very Likely / Highly Probable": + return 85 + elif scale_value == "Almost Certain / Nearly Certain": + return 95 + else: + raise ValueError("STIX Confidence value cannot be determined for %s" % scale_value) + + +def value_to_dni(confidence_value): + """ + This method will transform an integer value into the DNI scale string + representation. + + Notes: + The scale for this confidence representation is the following. + 0-9 -> "Almost No Chance / Remote" + 10-19 -> "Very Unlikely / Highly Improbable" + 20-39 -> "Unlikely / Improbable" + 40-59 -> "Roughly Even Change / Roughly Even Odds" + 60-79 -> "Likely / Probable" + 80-89 -> "Very Likely / Highly Probable" + 90-100 -> "Almost Certain / Nearly Certain" + + Args: + confidence_value: An integer value between 0 and 100. + + Returns: + str: A string corresponding to the DNI scale. + + Raises: + ValueError: If `confidence_value` is out of bounds. + + """ + if 9 >= confidence_value >= 0: + return "Almost No Chance / Remote" + elif 19 >= confidence_value >= 10: + return "Very Unlikely / Highly Improbable" + elif 39 >= confidence_value >= 20: + return "Unlikely / Improbable" + elif 59 >= confidence_value >= 40: + return "Roughly Even Change / Roughly Even Odds" + elif 79 >= confidence_value >= 60: + return "Likely / Probable" + elif 89 >= confidence_value >= 80: + return "Very Likely / Highly Probable" + elif 100 >= confidence_value >= 90: + return "Almost Certain / Nearly Certain" + else: + raise ValueError("Range of values out of bounds: %s" % confidence_value) From b99d9e413250196e393a87b70fc19737bb700554 Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Wed, 11 Oct 2017 13:16:59 -0400 Subject: [PATCH 3/4] Update confidence docstrings --- stix2/confidence/scales.py | 211 +++++++++++++++++++++---------------- 1 file changed, 121 insertions(+), 90 deletions(-) diff --git a/stix2/confidence/scales.py b/stix2/confidence/scales.py index 6ee1d64..6d8882d 100644 --- a/stix2/confidence/scales.py +++ b/stix2/confidence/scales.py @@ -7,12 +7,16 @@ def none_low_med_high_to_value(scale_value): This method will transform a string value from the None / Low / Med / High scale to its confidence integer representation. - Notes: - The scale for this confidence representation is the following. - "None" -> 0 - "Low" -> 15 - "Med" -> 50 - "High" -> 85 + The scale for this confidence representation is the following: + ==================== ===================== + None/ Low/ Med/ High STIX Confidence Value + ==================== ===================== + Not Specified Not Specified + None 0 + Low 15 + Med 50 + High 85 + ==================== ===================== Args: scale_value: A string value from the scale. Accepted strings are @@ -42,12 +46,15 @@ def value_to_none_low_medium_high(confidence_value): This method will transform an integer value into the None / Low / Med / High scale string representation. - Notes: - The scale for this confidence representation is the following. - 0 -> "None" - 1-29 -> "Low" - 30-69 -> "Med" - 70-100 -> "High" + The scale for this confidence representation is the following: + =============== ==================== + Range of Values None/ Low/ Med/ High + =============== ==================== + 0 None + 1-29 Low + 30-69 Med + 70-100 High + =============== ==================== Args: confidence_value: An integer value between 0 and 100. @@ -76,19 +83,22 @@ def zero_ten_to_value(scale_value): This method will transform a string value from the 0-10 scale to its confidence integer representation. - Notes: - The scale for this confidence representation is the following. - "0" -> 0 - "1" -> 10 - "2" -> 20 - "3" -> 30 - "4" -> 40 - "5" -> 50 - "6" -> 60 - "7" -> 70 - "8" -> 80 - "9" -> 90 - "10" -> 100 + The scale for this confidence representation is the following: + ==================== ===================== + 0-10 Scale STIX Confidence Value + ==================== ===================== + 0 0 + 1 10 + 2 20 + 3 30 + 4 40 + 5 50 + 6 60 + 7 70 + 8 80 + 9 90 + 10 100 + ==================== ===================== Args: scale_value: A string value from the scale. Accepted strings are "0" @@ -133,19 +143,22 @@ def value_to_zero_ten(confidence_value): This method will transform an integer value into the 0-10 scale string representation. - Notes: - The scale for this confidence representation is the following. - 0-4 -> "0" - 5-14 -> "1" - 15-24 -> "2" - 25-34 -> "3" - 35-44 -> "4" - 45-54 -> "5" - 55-64 -> "6" - 65-74 -> "7" - 75-84 -> "8" - 85-94 -> "9" - 95-100 -> "10" + The scale for this confidence representation is the following: + =============== ========== + Range of Values 0-10 Scale + =============== ========== + 0-4 0 + 5-14 1 + 15-24 2 + 25-34 3 + 35-44 4 + 45-54 5 + 55-64 6 + 65-74 7 + 75-84 8 + 85-94 9 + 95-100 10 + =============== ========== Args: confidence_value: An integer value between 0 and 100. @@ -188,14 +201,17 @@ def admiralty_credibility_to_value(scale_value): This method will transform a string value from the Admiralty Credibility scale to its confidence integer representation. - Notes: - The scale for this confidence representation is the following. - "6 - Truth cannot be judged" -> N/A - "5 - Improbable" -> 10 - "4 - Doubtful" -> 30 - "3 - Possibly True" -> 50 - "2 - Probably True" -> 70 - "1 - Confirmed by other sources" -> 90 + The scale for this confidence representation is the following: + ============================== ===================== + Admiralty Credibility STIX Confidence Value + ============================== ===================== + 6 - Truth cannot be judged (Not present) + 5 - Improbable 10 + 4 - Doubtful 30 + 3 - Possibly True 50 + 2 - Probably True 70 + 1 - Confirmed by other sources 90 + ============================== ===================== Args: scale_value: A string value from the scale. Accepted strings are @@ -232,14 +248,17 @@ def value_to_admiralty_credibility(confidence_value): This method will transform an integer value into the Admiralty Credibility scale string representation. - Notes: - The scale for this confidence representation is the following. - N/A -> "6 - Truth cannot be judged" - 0-19 -> "5 - Improbable" - 20-39 -> "4 - Doubtful" - 40-59 -> "3 - Possibly True" - 60-79 -> "2 - Probably True" - 80-100 -> "1 - Confirmed by other sources" + The scale for this confidence representation is the following: + =============== ============================== + Range of Values Admiralty Credibility + =============== ============================== + N/A 6 - Truth cannot be judged + 0-19 5 - Improbable + 20-39 4 - Doubtful + 40-59 3 - Possibly True + 60-79 2 - Probably True + 80-100 1 - Confirmed by other sources + =============== ============================== Args: confidence_value: An integer value between 0 and 100. @@ -271,15 +290,18 @@ def wep_to_value(scale_value): This method will transform a string value from the WEP scale to its confidence integer representation. - Notes: - The scale for this confidence representation is the following. - "Impossible" -> 0 - "Highly Unlikely/Almost Certainly Not" -> 10 - "Unlikely/Probably Not" -> 20 - "Even Chance" -> 50 - "Likely/Probable" -> 70 - "Highly likely/Almost Certain" -> 90 - "Certain" -> 100 + The scale for this confidence representation is the following: + ==================================== ===================== + WEP STIX Confidence Value + ==================================== ===================== + Impossible 0 + Highly Unlikely/Almost Certainly Not 10 + Unlikely/Probably Not 20 + Even Chance 50 + Likely/Probable 70 + Highly likely/Almost Certain 90 + Certain 100 + ==================================== ===================== Args: scale_value: A string value from the scale. Accepted strings are @@ -319,15 +341,18 @@ def value_to_wep(confidence_value): This method will transform an integer value into the WEP scale string representation. - Notes: - The scale for this confidence representation is the following. - 0 -> "Impossible" - 1-19 -> "Highly Unlikely/Almost Certainly Not" - 20-39 -> "Unlikely/Probably Not" - 40-59 -> "Even Chance" - 60-79 -> "Likely/Probable" - 80-99 -> "Highly likely/Almost Certain" - 100 -> "Certain" + The scale for this confidence representation is the following: + =============== ==================================== + Range of Values WEP + =============== ==================================== + 0 Impossible + 1-19 Highly Unlikely/Almost Certainly Not + 20-39 Unlikely/Probably Not + 40-59 Even Chance + 60-79 Likely/Probable + 80-99 Highly likely/Almost Certain + 100 Certain + =============== ==================================== Args: confidence_value: An integer value between 0 and 100. @@ -362,15 +387,18 @@ def dni_to_value(scale_value): This method will transform a string value from the DNI scale to its confidence integer representation. - Notes: - The scale for this confidence representation is the following. - "Almost No Chance / Remote" -> 5 - "Very Unlikely / Highly Improbable" -> 15 - "Unlikely / Improbable" -> 30 - "Roughly Even Change / Roughly Even Odds" -> 50 - "Likely / Probable" -> 70 - "Very Likely / Highly Probable" -> 85 - "Almost Certain / Nearly Certain" -> 95 + The scale for this confidence representation is the following: + ======================================= ===================== + DNI Scale STIX Confidence Value + ======================================= ===================== + Almost No Chance / Remote 5 + Very Unlikely / Highly Improbable 15 + Unlikely / Improbable 30 + Roughly Even Change / Roughly Even Odds 50 + Likely / Probable 70 + Very Likely / Highly Probable 85 + Almost Certain / Nearly Certain 95 + ======================================= ===================== Args: scale_value: A string value from the scale. Accepted strings are @@ -410,15 +438,18 @@ def value_to_dni(confidence_value): This method will transform an integer value into the DNI scale string representation. - Notes: - The scale for this confidence representation is the following. - 0-9 -> "Almost No Chance / Remote" - 10-19 -> "Very Unlikely / Highly Improbable" - 20-39 -> "Unlikely / Improbable" - 40-59 -> "Roughly Even Change / Roughly Even Odds" - 60-79 -> "Likely / Probable" - 80-89 -> "Very Likely / Highly Probable" - 90-100 -> "Almost Certain / Nearly Certain" + The scale for this confidence representation is the following: + =============== ======================================= + Range of Values DNI Scale + =============== ======================================= + 0-9 Almost No Chance / Remote + 10-19 Very Unlikely / Highly Improbable + 20-39 Unlikely / Improbable + 40-59 Roughly Even Change / Roughly Even Odds + 60-79 Likely / Probable + 80-89 Very Likely / Highly Probable + 90-100 Almost Certain / Nearly Certain + =============== ======================================= Args: confidence_value: An integer value between 0 and 100. From c4c2fb950ec4b58a1d2ace21893c02a1e408bd9b Mon Sep 17 00:00:00 2001 From: Emmanuelle Vargas-Gonzalez Date: Wed, 11 Oct 2017 13:30:26 -0400 Subject: [PATCH 4/4] Implement LanguageContent object. Update GranularMarking and other missing properties --- stix2/common.py | 36 ++++++++++++++++++++++++++++++++---- stix2/observables.py | 4 +++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/stix2/common.py b/stix2/common.py index 2946fdc..0d624ff 100644 --- a/stix2/common.py +++ b/stix2/common.py @@ -4,9 +4,10 @@ from collections import OrderedDict from .base import _STIXBase from .markings import _MarkingsMixin -from .properties import (HashesProperty, IDProperty, ListProperty, Property, - ReferenceProperty, SelectorProperty, StringProperty, - TimestampProperty, TypeProperty) +from .properties import (BooleanProperty, DictionaryProperty, HashesProperty, + IDProperty, ListProperty, Property, ReferenceProperty, + SelectorProperty, StringProperty, TimestampProperty, + TypeProperty) from .utils import NOW, get_dict @@ -39,10 +40,37 @@ class GranularMarking(_STIXBase): _properties = OrderedDict() _properties.update([ - ('marking_ref', ReferenceProperty(required=True, type="marking-definition")), + ('lang', StringProperty()), + ('marking_ref', ReferenceProperty(type="marking-definition")), # TODO: In 2.0 is required, not in 2.1 ('selectors', ListProperty(SelectorProperty, required=True)), ]) + def _check_object_constraints(self): + super(GranularMarking, self)._check_object_constraints() + self._check_at_least_one_property(["lang", "marking_ref"]) + + +class LanguageContent(_STIXBase): + _type = 'language-content' + _properties = OrderedDict() + _properties.update([ + ('type', TypeProperty(_type)), + ('id', IDProperty(_type)), + ('created_by_ref', ReferenceProperty(type="identity")), + ('created', TimestampProperty(default=lambda: NOW, precision='millisecond')), + ('modified', TimestampProperty(default=lambda: NOW, precision='millisecond')), + ('object_ref', ReferenceProperty(required=True)), + # TODO: 'object_modified' it MUST be an exact match for the modified time of the STIX Object (SRO or SDO) being referenced. + ('object_modified', TimestampProperty(required=True)), + # TODO: 'contents' https://docs.google.com/document/d/1ShNq4c3e1CkfANmD9O--mdZ5H0O_GLnjN28a_yrEaco/edit#heading=h.cfz5hcantmvx + ('contents', DictionaryProperty(required=True)), + ('revoked', BooleanProperty()), + ('labels', ListProperty(StringProperty)), + ('external_references', ListProperty(ExternalReference)), + ('object_marking_refs', ListProperty(ReferenceProperty(type="marking-definition"))), + ('granular_markings', ListProperty(GranularMarking)), + ]) + class TLPMarking(_STIXBase): diff --git a/stix2/observables.py b/stix2/observables.py index 57add29..45c3066 100644 --- a/stix2/observables.py +++ b/stix2/observables.py @@ -98,7 +98,7 @@ class AutonomousSystem(_Observable): _properties = OrderedDict() _properties.update([ ('type', TypeProperty(_type)), - ('number', IntegerProperty()), + ('number', IntegerProperty(required=True)), ('name', StringProperty()), ('rir', StringProperty()), ('extensions', ExtensionsProperty(enclosing_type=_type)), @@ -459,6 +459,8 @@ class SocketExt(_Extension): "SOCK_RDM", "SOCK_SEQPACKET", ])), + ('socket_descriptor', IntegerProperty()), + ('socket_handle', IntegerProperty()) ])