"""STIX2 Error Classes.""" class STIXError(Exception): """Base class for errors generated in the stix2 library.""" class ObjectConfigurationError(STIXError): """ Represents specification violations regarding the composition of STIX objects. """ pass class InvalidValueError(ObjectConfigurationError): """An invalid value was provided to a STIX object's ``__init__``.""" def __init__(self, cls, prop_name, reason): super(InvalidValueError, self).__init__() self.cls = cls self.prop_name = prop_name self.reason = reason def __str__(self): msg = "Invalid value for {0.cls.__name__} '{0.prop_name}': {0.reason}" return msg.format(self) class PropertyPresenceError(ObjectConfigurationError): """ Represents an invalid combination of properties on a STIX object. This class can be used directly when the object requirements are more complicated and none of the more specific exception subclasses apply. """ def __init__(self, message, cls): super(PropertyPresenceError, self).__init__(message) self.cls = cls class MissingPropertiesError(PropertyPresenceError): """Missing one or more required properties when constructing STIX object.""" def __init__(self, cls, properties): self.properties = sorted(properties) msg = "No values for required properties for {0}: ({1}).".format( cls.__name__, ", ".join(x for x in self.properties), ) super(MissingPropertiesError, self).__init__(msg, cls) class ExtraPropertiesError(PropertyPresenceError): """One or more extra properties were provided when constructing STIX object.""" def __init__(self, cls, properties): self.properties = sorted(properties) msg = "Unexpected properties for {0}: ({1}).".format( cls.__name__, ", ".join(x for x in self.properties), ) super(ExtraPropertiesError, self).__init__(msg, cls) class MutuallyExclusivePropertiesError(PropertyPresenceError): """Violating interproperty mutually exclusive constraint of a STIX object type.""" def __init__(self, cls, properties): self.properties = sorted(properties) msg = "The ({1}) properties for {0} are mutually exclusive.".format( cls.__name__, ", ".join(x for x in self.properties), ) super(MutuallyExclusivePropertiesError, self).__init__(msg, cls) class DependentPropertiesError(PropertyPresenceError): """Violating interproperty dependency constraint of a STIX object type.""" def __init__(self, cls, dependencies): self.dependencies = dependencies msg = "The property dependencies for {0}: ({1}) are not met.".format( cls.__name__, ", ".join(name for x in self.dependencies for name in x), ) super(DependentPropertiesError, self).__init__(msg, cls) class AtLeastOnePropertyError(PropertyPresenceError): """Violating a constraint of a STIX object type that at least one of the given properties must be populated.""" def __init__(self, cls, properties): self.properties = sorted(properties) msg = "At least one of the ({1}) properties for {0} must be " \ "populated.".format( cls.__name__, ", ".join(x for x in self.properties), ) super(AtLeastOnePropertyError, self).__init__(msg, cls) class DictionaryKeyError(ObjectConfigurationError): """Dictionary key does not conform to the correct format.""" def __init__(self, key, reason): super(DictionaryKeyError, self).__init__() self.key = key self.reason = reason def __str__(self): msg = "Invalid dictionary key {0.key}: ({0.reason})." return msg.format(self) class InvalidObjRefError(ObjectConfigurationError): """A STIX Cyber Observable Object contains an invalid object reference.""" def __init__(self, cls, prop_name, reason): super(InvalidObjRefError, self).__init__() self.cls = cls self.prop_name = prop_name self.reason = reason def __str__(self): msg = "Invalid object reference for '{0.cls.__name__}:{0.prop_name}': {0.reason}" return msg.format(self) class InvalidSelectorError(ObjectConfigurationError): """Granular Marking selector violation. The selector must resolve into an existing STIX object property.""" def __init__(self, cls, key): super(InvalidSelectorError, self).__init__() self.cls = cls self.key = key def __str__(self): msg = "Selector {0} in {1} is not valid!" return msg.format(self.key, self.cls.__class__.__name__) class TLPMarkingDefinitionError(ObjectConfigurationError): """Marking violation. The marking-definition for TLP MUST follow the mandated instances from the spec.""" def __init__(self, user_obj, spec_obj): super(TLPMarkingDefinitionError, self).__init__() self.user_obj = user_obj self.spec_obj = spec_obj def __str__(self): msg = "Marking {0} does not match spec marking {1}!" return msg.format(self.user_obj, self.spec_obj) class ImmutableError(STIXError): """Attempted to modify an object after creation.""" def __init__(self, cls, key): super(ImmutableError, self).__init__() self.cls = cls self.key = key def __str__(self): msg = "Cannot modify '{0.key}' property in '{0.cls.__name__}' after creation." return msg.format(self) class UnmodifiablePropertyError(STIXError): """Attempted to modify an unmodifiable property of object when creating a new version.""" def __init__(self, unchangable_properties): super(UnmodifiablePropertyError, self).__init__() self.unchangable_properties = unchangable_properties def __str__(self): msg = "These properties cannot be changed when making a new version: {0}." return msg.format(", ".join(self.unchangable_properties)) class RevokeError(STIXError): """Attempted an operation on a revoked object.""" def __init__(self, called_by): super(RevokeError, self).__init__() self.called_by = called_by def __str__(self): if self.called_by == "revoke": return "Cannot revoke an already revoked object." else: return "Cannot create a new version of a revoked object." class ParseError(STIXError): """Could not parse object.""" def __init__(self, msg): super(ParseError, self).__init__(msg) class CustomContentError(STIXError): """Custom STIX Content (SDO, Observable, Extension, etc.) detected.""" def __init__(self, msg): super(CustomContentError, self).__init__(msg) class MarkingNotFoundError(STIXError): """Marking violation. The marking reference must be present in SDO or SRO.""" def __init__(self, cls, key): super(MarkingNotFoundError, self).__init__() self.cls = cls self.key = key def __str__(self): msg = "Marking {0} was not found in {1}!" return msg.format(self.key, self.cls.__class__.__name__) class STIXDeprecationWarning(DeprecationWarning): """ Represents usage of a deprecated component of a STIX specification. """ pass class DuplicateRegistrationError(STIXError): """A STIX object with the same type as an existing object is being registered""" def __init__(self, obj_type, reg_obj_type): super(DuplicateRegistrationError, self).__init__() self.obj_type = obj_type self.reg_obj_type = reg_obj_type def __str__(self): msg = "A(n) {0} with type '{1}' already exists and cannot be registered again" return msg.format(self.obj_type, self.reg_obj_type)