import stix2

indicator = stix2.v21.Indicator(
    id='indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c',
    created='2014-02-20T09:16:08.989000Z',
    modified='2014-02-20T09:16:08.989000Z',
    name='File hash for Poison Ivy variant',
    description='This file hash indicates that a sample of Poison Ivy is present.',
    labels=[
        'malicious-activity',
    ],
    rank=5,
    toxicity=8,
    pattern='[file:hashes.\'SHA-256\' = \'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c\']',
    pattern_type='stix',
    valid_from='2014-02-20T09:00:00.000000Z',
    extensions={
        "extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8" : {
            'extension_type': 'toplevel-property-extension',
        },
    }
)

print(indicator.serialize(pretty=True))

"""
Explanation: STIX Extensions
This page is specific for the STIX Extensions mechanism defined in STIX 2.1 CS 03. For the deprecated STIX Customization mechanisms see the Custom section.
Top Level Property Extensions
The example below shows how to create an indicator object with a toplevel-property-extension.  Because an unregistered toplevel property extension is present, any unrecognized toplevel properties are assumed to be extension properties.  So the library lets them pass.
End of explanation
"""


TOPLEVEL_EXTENSION_DEFINITION_ID = 'extension-definition--dd73de4f-a7f3-49ea-8ec1-8e884196b7a8'

@stix2.v21.CustomExtension(
    TOPLEVEL_EXTENSION_DEFINITION_ID, [
        ('rank', stix2.properties.IntegerProperty(required=True)),
        ('toxicity', stix2.properties.IntegerProperty(required=True)),
    ],
)
class ExtensionTopLevel:
    extension_type = 'toplevel-property-extension'

indicator = stix2.v21.Indicator(
    id='indicator--e97bfccf-8970-4a3c-9cd1-5b5b97ed5d0c',
    created='2014-02-20T09:16:08.989000Z',
    modified='2014-02-20T09:16:08.989000Z',
    name='File hash for Poison Ivy variant',
    description='This file hash indicates that a sample of Poison Ivy is present.',
    labels=[
        'malicious-activity',
    ],
    rank=5,
    toxicity=8,
    pattern='[file:hashes.\'SHA-256\' = \'ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c\']',
    pattern_type='stix',
    valid_from='2014-02-20T09:00:00.000000Z',
    extensions={
        TOPLEVEL_EXTENSION_DEFINITION_ID : {
            'extension_type': 'toplevel-property-extension',
        },
    }
)

print(indicator.serialize(pretty=True))

"""
Explanation: Using CustomExtension decorator
However, in order to define which properties are actually included with an extension, the @CustomExtension decorator can be used to register an extension type and its properties with stix2. Use the extension_type class variable to define what kind of extension it is. Then its id can be passed into objects that use this extension.
End of explanation
"""


@stix2.v21.CustomObservable(
    'my-favorite-sco', [
        ('name', stix2.properties.StringProperty(required=True)),
        ('some_network_protocol_field', stix2.properties.StringProperty(required=True)),
    ], ['name', 'some_network_protocol_field'], 'extension-definition--150c1738-28c9-44d0-802d-70523218240b',
)
class MyFavSCO:
    pass

my_favorite_sco = MyFavSCO(
    id='my-favorite-sco--f9dbe89c-0030-4a9d-8b78-0dcd0a0de874',
    name='This is the name of my favorite SCO',
    some_network_protocol_field='value',
)

print(my_favorite_sco.serialize(pretty=True))

"""
Explanation: Using CustomObservable for Extension Definition
Similarly, when registering new objects via @CustomObservable you can pass the extension-definition id that defines this new SCO. 

Note:
Creating an instance of an extension object does not mean it is registered in the library. Please use the appropriate decorator for this step: @CustomExtension, @CustomObject, @CustomObservable, @CustomMarking
End of explanation
"""


import stix2
import stix2.properties

MARKING_EXTENSION_ID = 'extension-definition--a932fcc6-e032-176c-126f-cb970a5a1fff'

@stix2.CustomExtension(MARKING_EXTENSION_ID, [
    ('some_marking_field', stix2.properties.StringProperty(required=True))
])
class MyFavMarking:
    extension_type = 'property-extension'

my_favorite_marking = stix2.MarkingDefinition(
    name='This is the name of my favorite Marking',
    extensions={
        MARKING_EXTENSION_ID: MyFavMarking(
            some_marking_field='value'
        )
    }
)

print(my_favorite_marking.serialize(pretty=True))

"""
Explanation: Custom Markings
The example below show how to create a user-defined marking based on an extension.  The STIX marking-definition object is essentially a base upon which you build the particulars of your marking, via an extension.  This is done in the same way as any other extension.  Marking definitions are no different in this regard.  The below example illustrates an alternative to building the extension entirely as a dictionary: it can also be built by instantiating the registered class.
End of explanation
"""


invalid_refs = ['bundle', 'language-content', 'marking-definition', 'relationship', 'sighting', 'foobar']

@stix2.v21.CustomObject(
    'my-favorite-sro', [
        ('name', stix2.properties.StringProperty(required=False)),
        ('some_source_ref', stix2.properties.ReferenceProperty(invalid_types=invalid_refs, spec_version='2.1', required=True)),
        ('some_target_ref', stix2.properties.ReferenceProperty(invalid_types=invalid_refs, spec_version='2.1', required=True)),
    ], extension_name='extension-definition--e96690a5-dc13-4f27-99dd-0f2188ad74ce', is_sdo=False,
)
class MyFavSRO:
    pass


my_favorite_sro = MyFavSRO(
    name="My First SRO",
    some_source_ref="identity--b1da8c3e-34d8-470f-9d2b-392e275f1f7d",
    some_target_ref="identity--1ddfed54-e8cd-49c9-9c7d-8d1b03c94685",
)

print(my_favorite_sro.serialize(pretty=True))

"""
Explanation: Using CustomObject for Extension Definition
Similar to the examples above, the same can be done for SDOs and SROs.
End of explanation
"""


