def __init__(self, object_generator, config=None, stix_version="2.1"):
        """
        Initialize this reference graph generator.

        :param object_generator: An instance of the built-in object generator
            to use for generating the objects.
        :param config: Config settings for the generator.
        """

        self.__config = config or Config()
        self.__object_generator = object_generator
        self.__stix_version = stix_version

        # A big problem that must be solved is how to stop the graph from
        # growing too large.  We can't simply stop generating objects, because
        # there must be no dangling references.  We also can't just keep
        # generating objects because the graph can balloon to enormous size.
        # My solution is to take advantage of the reference minimization
        # capability of the built-in object generator.  If we minimize
        # references, we minimize the number of new objects which need to be
        # generated, and that acts to put the brakes on growth.  We can't
        # minimize references all the time, because then the graph wouldn't
        # be able to grow much.  So we need two generators: one which generates
        # objects "normally" and is used to grow the graph, and one which
        # minimizes references, which is used to halt growth when we need it to
        # stop.

        halt_generator_config_dict = vars(object_generator.config).copy()
        halt_generator_config_dict["minimize_ref_properties"] = True
        halt_generator_config = stix2generator.generation.object_generator\
            .Config(
                **halt_generator_config_dict
            )
        self.__halt_generator = stix2generator.create_object_generator(
            halt_generator_config)
Beispiel #2
0
def test_stix2_parsing():
    obj_gen_config = stix2generator.generation.object_generator.Config(
        minimize_ref_properties=False)
    obj_gen = stix2generator.create_object_generator(obj_gen_config)

    ref_graph_gen = stix2generator.generation.reference_graph_generator \
        .ReferenceGraphGenerator(obj_gen, stix_version="2.1")

    graph1 = {
        "identity--74fa9f1b-897e-40dc-8f1c-d2f531c956bb": {
            "id": "identity--74fa9f1b-897e-40dc-8f1c-d2f531c956bb",
            "type": "identity",
            "spec_version": "2.1"
            # Omit the required "name" property.
            # Should be ok since the property is not used by any generators,
            # and we don't expect this dict to be parsed and produce any
            # validation errors.
        }
    }

    _, graph2 = ref_graph_gen.generate(preexisting_objects=graph1)

    # ensure graph2 absorbed graph1
    assert all(id_ in graph2 for id_ in graph1)

    # ensure our preexisting identity is still a dict
    assert isinstance(graph2["identity--74fa9f1b-897e-40dc-8f1c-d2f531c956bb"],
                      dict)
Beispiel #3
0
def test_nonconst_object_spec_all_types(cleanup_stix2):
    spec = {
        "type": "object",
        "properties": {
            "type": "my-type",
            "int": {"type": "integer"},
            "number": {"type": "number"},
            "boolean": {"type": "boolean"},
            "string": {"type": "string"},
            "array": {"type": "array", "items": {"type": "integer"}},
            "object": {
                "type": "object",
                "properties": {
                    "subprop1": {"type": "integer"},
                    "subprop2": {"type": "string"}
                }
            }
        }
    }

    stix2_register_custom(spec, "my-type", "2.1")

    gen = stix2generator.create_object_generator()
    random_dict = gen.generate_from_spec(spec)
    stix_obj = stix2.parse(random_dict, version="2.1")

    # Make sure all props from the dict came through in the stix2 object
    for prop, value in random_dict.items():
        assert stix_obj[prop] == value
Beispiel #4
0
def test_not_parsing(num_trials):
    obj_gen_config = stix2generator.generation.object_generator.Config(
        minimize_ref_properties=False
    )
    obj_gen = stix2generator.create_object_generator(obj_gen_config)

    ref_graph_config = stix2generator.generation.reference_graph_generator \
        .Config(
            parse=False
        )
    ref_graph_gen = stix2generator.generation.reference_graph_generator \
        .ReferenceGraphGenerator(obj_gen, ref_graph_config, stix_version="2.1")

    identity = stix2.v21.Identity(
        name="Alice"
    )

    for _ in range(num_trials):
        graph1 = {
            identity.id: identity
        }

        _, graph2 = ref_graph_gen.generate(preexisting_objects=graph1)

        # ensure graph2 absorbed graph1
        assert graph1.keys() <= graph2.keys()

        # Ensure the only parsed object is our original identity.
        for id_, obj in graph2.items():
            if id_ == identity.id:
                assert isinstance(obj, stix2.v21.Identity)

            else:
                assert isinstance(obj, dict)
def test_stix2_parsing(num_trials):
    obj_gen_config = stix2generator.generation.object_generator.Config(
        minimize_ref_properties=False)
    obj_gen = stix2generator.create_object_generator(obj_gen_config)

    ref_graph_gen = stix2generator.generation.reference_graph_generator \
        .ReferenceGraphGenerator(obj_gen, stix_version="2.1")

    identity = {
        "id": "identity--74fa9f1b-897e-40dc-8f1c-d2f531c956bb",
        "type": "identity",
        "spec_version": "2.1"
        # Omit the required "name" property.
        # Should be ok since the property is not used by any generators,
        # and we don't expect this dict to be parsed and produce any
        # validation errors.
    }

    for _ in range(num_trials):
        graph1 = {identity["id"]: identity}

        _, graph2 = ref_graph_gen.generate(preexisting_objects=graph1)

        # ensure graph2 absorbed graph1
        assert graph1.keys() <= graph2.keys()

        # ensure our preexisting identity is still a dict, but other objects
        # were parsed.
        for id_, obj in graph2.items():
            if id_ == identity["id"]:
                assert isinstance(obj, dict)
            else:
                assert isinstance(obj, stix2.base._STIXBase)
def generator_all_props():
    """
    Creates a generator which includes all optional properties.
    """
    config = stix2generator.generation.object_generator.Config(
        minimize_ref_properties=False, optional_property_probability=1)

    generator = stix2generator.create_object_generator(config, None, "2.1")

    return generator
def generator_random_props():
    """
    Creates a generator which randomly includes or excludes properties.
    """
    config = stix2generator.generation.object_generator.Config(
        minimize_ref_properties=False)

    generator = stix2generator.create_object_generator(config, None, "2.1")

    return generator
Beispiel #8
0
def test_bad_seed():
    obj_gen_config = stix2generator.generation.object_generator.Config(
        minimize_ref_properties=False)
    obj_gen = stix2generator.create_object_generator(obj_gen_config)

    ref_graph_gen = stix2generator.generation.reference_graph_generator \
        .ReferenceGraphGenerator(obj_gen, stix_version="2.1")

    with pytest.raises(
            stix2generator.exceptions.GeneratableSTIXTypeNotFoundError):
        ref_graph_gen.generate("foo")
def test_no_dangling_references(num_trials):
    obj_gen_config = stix2generator.generation.object_generator.Config(
        minimize_ref_properties=False)
    obj_gen = stix2generator.create_object_generator(obj_gen_config)
    ref_graph_gen = stix2generator.generation.reference_graph_generator \
        .ReferenceGraphGenerator(
            obj_gen
        )

    for _ in range(num_trials):
        _, graph = ref_graph_gen.generate()
        assert not stix2generator.test.utils.has_dangling_references(graph)
Beispiel #10
0
def test_seeds(num_trials, seed_type):
    obj_gen_config = stix2generator.generation.object_generator.Config(
        minimize_ref_properties=False)
    obj_gen = stix2generator.create_object_generator(obj_gen_config)

    ref_graph_gen = stix2generator.generation.reference_graph_generator \
        .ReferenceGraphGenerator(obj_gen, stix_version="2.1")

    for _ in range(num_trials):

        _, graph = ref_graph_gen.generate(seed_type)

        # Ensure the graph has at least one object of type seed_type.
        assert any(
            stix2generator.utils.is_stix_type(
                obj, seed_type, stix_version="2.1") for obj in graph.values())
Beispiel #11
0
def test_graph_random(num_trials):
    obj_gen_config = stix2generator.generation.object_generator.Config(
        minimize_ref_properties=False)
    obj_gen = stix2generator.create_object_generator(obj_gen_config)
    graph_gen_config = stix2generator.generation.reference_graph_generator\
        .Config(
            graph_type="random",
            inverse_property_constraints="delete"
        )

    ref_graph_gen = stix2generator.generation.reference_graph_generator\
        .ReferenceGraphGenerator(obj_gen, graph_gen_config)

    for _ in range(num_trials):
        _, graph = ref_graph_gen.generate()
        assert not stix2generator.test.utils.has_dangling_references(graph)
        assert stix2generator.test.utils.is_connected(graph)
Beispiel #12
0
def test_preexisting_objects():
    obj_gen_config = stix2generator.generation.object_generator.Config(
        minimize_ref_properties=False)
    obj_gen = stix2generator.create_object_generator(obj_gen_config)

    ref_graph_gen = stix2generator.generation.reference_graph_generator \
        .ReferenceGraphGenerator(obj_gen, stix_version="2.1")

    _, graph1 = ref_graph_gen.generate()

    _, graph2 = ref_graph_gen.generate(preexisting_objects=graph1)

    # just ensure graph2 absorbed graph1.  Anything else we can test?
    assert all(id_ in graph2 for id_ in graph1)

    # ensure all objects got parsed ok
    assert all(
        isinstance(obj, stix2.base._STIXBase) for obj in graph2.values())
Beispiel #13
0
def test_graph_delete_inverse_properties(num_trials):
    obj_gen_config = stix2generator.generation.object_generator.Config(
        minimize_ref_properties=False)
    obj_gen = stix2generator.create_object_generator(obj_gen_config)

    graph_gen_config = stix2generator.generation.reference_graph_generator\
        .Config(
            inverse_property_constraints="delete"
        )
    ref_graph_gen = stix2generator.generation.reference_graph_generator\
        .ReferenceGraphGenerator(obj_gen, graph_gen_config)

    for _ in range(num_trials):
        # I feel like I should hard-code a STIX object type I know to contain
        # lots of reference properties and have applicable constraints, to have
        # a high likelihood that reference properties will be generated, the
        # graph will grow, and there will be some applicable constraints to
        # test.
        _, graph = ref_graph_gen.generate("network-traffic")
        assert not _constraints_applicable(graph)
def default_object_generator():
    return stix2generator.create_object_generator(stix_version="2.1")