WIP adding is_sdo() et al functions to this library. On hold
while I address circular import problems.pull/1/head
							parent
							
								
									03b3423cbb
								
							
						
					
					
						commit
						fa6cff8a34
					
				
							
								
								
									
										184
									
								
								stix2/utils.py
								
								
								
								
							
							
						
						
									
										184
									
								
								stix2/utils.py
								
								
								
								
							| 
						 | 
				
			
			@ -9,6 +9,11 @@ import pytz
 | 
			
		|||
import six
 | 
			
		||||
 | 
			
		||||
import stix2
 | 
			
		||||
try:
 | 
			
		||||
    import stix2.parsing as mappings
 | 
			
		||||
except ImportError:
 | 
			
		||||
    import stix2.core as mappings
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Sentinel value for properties that should be set to the current time.
 | 
			
		||||
# We can't use the standard 'default' approach, since if there are multiple
 | 
			
		||||
| 
						 | 
				
			
			@ -313,18 +318,177 @@ def get_type_from_id(stix_id):
 | 
			
		|||
    return stix_id.split('--', 1)[0]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_marking(obj_or_id):
 | 
			
		||||
    """Determines whether the given object or object ID is/is for a marking
 | 
			
		||||
    definition.
 | 
			
		||||
def _stix_type_of(value):
 | 
			
		||||
    """
 | 
			
		||||
    Get a STIX type from the given value: if a STIX ID is passed, the type
 | 
			
		||||
    prefix is extracted; if string which is not a STIX ID is passed, it is
 | 
			
		||||
    assumed to be a STIX type and is returned; otherwise it is assumed to be a
 | 
			
		||||
    mapping with a "type" property, and the value of that property is returned.
 | 
			
		||||
 | 
			
		||||
    :param obj_or_id: A STIX object or object ID as a string.
 | 
			
		||||
    :return: True if a marking definition, False otherwise.
 | 
			
		||||
    :param value: A mapping with a "type" property, or a STIX ID or type
 | 
			
		||||
        as a string
 | 
			
		||||
    :return: A STIX type
 | 
			
		||||
    """
 | 
			
		||||
    if isinstance(value, str):
 | 
			
		||||
        if "--" in value:
 | 
			
		||||
            type_ = get_type_from_id(value)
 | 
			
		||||
        else:
 | 
			
		||||
            type_ = value
 | 
			
		||||
    else:
 | 
			
		||||
        type_ = value["type"]
 | 
			
		||||
 | 
			
		||||
    return type_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def _get_stix2_class_maps(stix_version):
 | 
			
		||||
    """
 | 
			
		||||
    Get the stix2 class mappings for the given STIX version.
 | 
			
		||||
 | 
			
		||||
    :param stix_version: A STIX version as a string
 | 
			
		||||
    :return: The class mappings.  This will be a dict mapping from some general
 | 
			
		||||
        category name, e.g. "object" to another mapping from STIX type
 | 
			
		||||
        to a stix2 class.
 | 
			
		||||
    """
 | 
			
		||||
    stix_vid = "v" + stix_version.replace(".", "")
 | 
			
		||||
    cls_maps = mappings.STIX2_OBJ_MAPS[stix_vid]
 | 
			
		||||
 | 
			
		||||
    return cls_maps
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_sdo(value, stix_version=stix2.DEFAULT_VERSION):
 | 
			
		||||
    """
 | 
			
		||||
    Determine whether the given object, type, or ID is/is for an SDO.
 | 
			
		||||
 | 
			
		||||
    :param value: A mapping with a "type" property, or a STIX ID or type
 | 
			
		||||
        as a string
 | 
			
		||||
    :param stix_version: A STIX version as a string
 | 
			
		||||
    :return: True if the type of the given value is an SDO type; False
 | 
			
		||||
        if not
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    if isinstance(obj_or_id, (stix2.base._STIXBase, dict)):
 | 
			
		||||
        result = obj_or_id["type"] == "marking-definition"
 | 
			
		||||
    else:
 | 
			
		||||
        # it's a string ID
 | 
			
		||||
        result = obj_or_id.startswith("marking-definition--")
 | 
			
		||||
    # Eventually this needs to be moved into the stix2 library (and maybe
 | 
			
		||||
    # improved?); see cti-python-stix2 github issue #450.
 | 
			
		||||
 | 
			
		||||
    cls_maps = _get_stix2_class_maps(stix_version)
 | 
			
		||||
    type_ = _stix_type_of(value)
 | 
			
		||||
    result = type_ in cls_maps["objects"] and type_ not in {
 | 
			
		||||
        "relationship", "sighting", "marking-definition", "bundle",
 | 
			
		||||
        "language-content"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return result
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_sco(value, stix_version=stix2.DEFAULT_VERSION):
 | 
			
		||||
    """
 | 
			
		||||
    Determine whether the given object, type, or ID is/is for an SCO.
 | 
			
		||||
 | 
			
		||||
    :param value: A mapping with a "type" property, or a STIX ID or type
 | 
			
		||||
        as a string
 | 
			
		||||
    :param stix_version: A STIX version as a string
 | 
			
		||||
    :return: True if the type of the given value is an SCO type; False
 | 
			
		||||
        if not
 | 
			
		||||
    """
 | 
			
		||||
    cls_maps = _get_stix2_class_maps(stix_version)
 | 
			
		||||
    type_ = _stix_type_of(value)
 | 
			
		||||
    result = type_ in cls_maps["observables"]
 | 
			
		||||
 | 
			
		||||
    return result
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_sro(value, stix_version=stix2.DEFAULT_VERSION):
 | 
			
		||||
    """
 | 
			
		||||
    Determine whether the given object, type, or ID is/is for an SCO.
 | 
			
		||||
 | 
			
		||||
    :param value: A mapping with a "type" property, or a STIX ID or type
 | 
			
		||||
        as a string
 | 
			
		||||
    :param stix_version: A STIX version as a string
 | 
			
		||||
    :return: True if the type of the given value is an SRO type; False
 | 
			
		||||
        if not
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    # No STIX version dependence here yet...
 | 
			
		||||
    type_ = _stix_type_of(value)
 | 
			
		||||
    result = type_ in ("sighting", "relationship")
 | 
			
		||||
 | 
			
		||||
    return result
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_object(value, stix_version=stix2.DEFAULT_VERSION):
 | 
			
		||||
    """
 | 
			
		||||
    Determine whether an object, type, or ID is/is for any STIX object.  This
 | 
			
		||||
    includes all SDOs, SCOs, meta-objects, and bundle.
 | 
			
		||||
 | 
			
		||||
    :param value: A mapping with a "type" property, or a STIX ID or type
 | 
			
		||||
        as a string
 | 
			
		||||
    :param stix_version: A STIX version as a string
 | 
			
		||||
    :return: True if the type of the given value is a valid STIX type with
 | 
			
		||||
        respect to the given STIX version; False if not
 | 
			
		||||
    """
 | 
			
		||||
    cls_maps = _get_stix2_class_maps(stix_version)
 | 
			
		||||
    type_ = _stix_type_of(value)
 | 
			
		||||
    result = type_ in cls_maps["observables"] or type_ in cls_maps["objects"]
 | 
			
		||||
 | 
			
		||||
    return result
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_marking(value, stix_version=stix2.DEFAULT_VERSION):
 | 
			
		||||
    """Determines whether the given value is/is for a marking definition.
 | 
			
		||||
 | 
			
		||||
    :param value: A STIX object, object ID, or type as a string.
 | 
			
		||||
    :param stix_version: A STIX version as a string
 | 
			
		||||
    :return: True if the value is/is for a marking definition, False otherwise.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    # No STIX version dependence here yet...
 | 
			
		||||
    type_ = _stix_type_of(value)
 | 
			
		||||
    result = type_ == "marking-definition"
 | 
			
		||||
 | 
			
		||||
    return result
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class STIXTypeClass(enum.Enum):
 | 
			
		||||
    """
 | 
			
		||||
    Represents different classes of STIX type.
 | 
			
		||||
    """
 | 
			
		||||
    SDO = 0
 | 
			
		||||
    SCO = 1
 | 
			
		||||
    SRO = 2
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def is_stix_type(value, stix_version=stix2.DEFAULT_VERSION, *types):
 | 
			
		||||
    """
 | 
			
		||||
    Determine whether the type of the given value satisfies the given
 | 
			
		||||
    constraints.  'types' must contain STIX types as strings, and/or the
 | 
			
		||||
    STIXTypeClass enum values.  STIX types imply an exact match constraint;
 | 
			
		||||
    STIXTypeClass enum values imply a more general constraint, that the object
 | 
			
		||||
    or type be in that class of STIX type.  These constraints are implicitly
 | 
			
		||||
    OR'd together.
 | 
			
		||||
 | 
			
		||||
    :param value: A mapping with a "type" property, or a STIX ID or type
 | 
			
		||||
        as a string
 | 
			
		||||
    :param stix_version: A STIX version as a string
 | 
			
		||||
    :param types: A sequence of STIX type strings or STIXTypeClass enum values
 | 
			
		||||
    :return: True if the object or type satisfies the constraints; False if not
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    for type_ in types:
 | 
			
		||||
        if type_ is STIXTypeClass.SDO:
 | 
			
		||||
            result = is_sdo(value, stix_version)
 | 
			
		||||
        elif type_ is STIXTypeClass.SCO:
 | 
			
		||||
            result = is_sco(value, stix_version)
 | 
			
		||||
        elif type_ is STIXTypeClass.SRO:
 | 
			
		||||
            result = is_sro(value, stix_version)
 | 
			
		||||
        else:
 | 
			
		||||
            # Assume a string STIX type is given instead of a class enum,
 | 
			
		||||
            # and just check for exact match.
 | 
			
		||||
            obj_type = _stix_type_of(value)
 | 
			
		||||
            result = is_object(obj_type, stix_version) and obj_type == type_
 | 
			
		||||
 | 
			
		||||
        if result:
 | 
			
		||||
            break
 | 
			
		||||
 | 
			
		||||
    else:
 | 
			
		||||
        result = False
 | 
			
		||||
 | 
			
		||||
    return result
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue