Struct Collection

Source
pub struct Collection { /* private fields */ }
Expand description

An immutable collection of STIX objects.

A collection has no special meaning beyond being a set of STIX objects all loaded in memory at once.

§Usage

Create a Collection by deserializing JSON into Bundle instances and then adding those to a CollectionBuilder. Once all bundles are loaded, call CollectionBuilder::build to finish the collection, which will index the objects and prepare the collection for querying.

Implementations§

Source§

impl Collection

Source

pub fn builder() -> CollectionBuilder

Create a new CollectionBuilder.

Source

pub fn get<'id, 'a: 'id, D>(&'a self, id: &'id Id) -> Option<Node<'a, D>>
where Ref<'id, 'a, D>: Resolve<Output = Node<'a, D>>,

Get the object identified by id if it is present in the collection. This function returns a Node which provides access to the object’s data and its relationships within the collection.

Examples found in repository?
examples/tools.rs (line 12)
4fn main() {
5    let enterprise = attck::enterprise();
6    let mimikatz_id = "tool--afc079f3-c0ea-4096-b75d-3f05338b7f60"
7        .parse::<Id>()
8        .unwrap();
9
10    // Knowing the ID and the expected return type, request the resource from the
11    // collection.
12    let mimikatz = enterprise.get::<Tool>(&mimikatz_id).unwrap();
13
14    println!(
15        "{} {}",
16        mimikatz.name(),
17        mimikatz.description().unwrap_or("<NO DESCRIPTION>")
18    );
19}
More examples
Hide additional examples
examples/print_matrix.rs (line 34)
21    pub fn new(matrix: Node<'a, Matrix>) -> Self {
22        let collection = matrix.collection();
23        // Annoyingly, MITRE does not publish SROs from tactics to techniques and instead relies on
24        // the kill_chain_phases property. The `stix` crate doesn't know about this relationship, so
25        // we do one pass to gather all the tactics and visit every attack_pattern to build the grid.
26        let mut tactics_by_shortname = HashMap::new();
27
28        // Cells are ordered to preserve the ordering from the Matrix declaration.
29        let mut columns = vec![];
30
31        let mut dangling_ids = BTreeSet::new();
32
33        for tactic_ref in &matrix.data().tactic_refs {
34            if let Some(tactic) = collection.get::<Tactic>(tactic_ref) {
35                // Use data() because &tactic.shortname doesn't live long enough
36                tactics_by_shortname.insert(&tactic.data().shortname, columns.len());
37                // Insert _after_ capturing the index of the value we just added or else our
38                // indices will be off by one.
39                columns.push((tactic.data(), vec![]));
40            } else {
41                dangling_ids.insert(tactic_ref);
42            }
43        }
44
45        for attack_pattern in matrix
46            .collection()
47            .attack_patterns()
48            .filter(|ap| ap.mitre.is_subtechnique == Some(false))
49        {
50            for phase in attack_pattern
51                .base
52                .kill_chain_phases
53                .iter()
54                .filter(|phase| phase.kill_chain_name == "mitre-attack")
55            {
56                if let Some(cell_index) = tactics_by_shortname.get(&phase.phase_name).copied() {
57                    columns[cell_index].1.push(attack_pattern.clone());
58                }
59            }
60        }
61
62        Self {
63            columns,
64            dangling_ids,
65        }
66    }
Source

pub fn is_empty(&self) -> bool

Get whether the collection has no items.

Source

pub fn len(&self) -> usize

Get the number of objects in the collection.

Source§

impl Collection

Accessors for STIX objects in the collection.

Source

pub fn attack_patterns<'a>( &'a self, ) -> impl Iterator<Item = Node<'a, AttackPattern>>

Examples found in repository?
examples/data_sources.rs (line 10)
6fn main() {
7    let enterprise = attck::enterprise();
8
9    let data_sources = enterprise
10        .attack_patterns()
11        .flat_map(|ap| &ap.data().mitre.data_sources)
12        .collect::<BTreeSet<_>>();
13
14    for data_source in data_sources {
15        println!("{}", data_source);
16    }
17}
More examples
Hide additional examples
examples/print_matrix.rs (line 47)
21    pub fn new(matrix: Node<'a, Matrix>) -> Self {
22        let collection = matrix.collection();
23        // Annoyingly, MITRE does not publish SROs from tactics to techniques and instead relies on
24        // the kill_chain_phases property. The `stix` crate doesn't know about this relationship, so
25        // we do one pass to gather all the tactics and visit every attack_pattern to build the grid.
26        let mut tactics_by_shortname = HashMap::new();
27
28        // Cells are ordered to preserve the ordering from the Matrix declaration.
29        let mut columns = vec![];
30
31        let mut dangling_ids = BTreeSet::new();
32
33        for tactic_ref in &matrix.data().tactic_refs {
34            if let Some(tactic) = collection.get::<Tactic>(tactic_ref) {
35                // Use data() because &tactic.shortname doesn't live long enough
36                tactics_by_shortname.insert(&tactic.data().shortname, columns.len());
37                // Insert _after_ capturing the index of the value we just added or else our
38                // indices will be off by one.
39                columns.push((tactic.data(), vec![]));
40            } else {
41                dangling_ids.insert(tactic_ref);
42            }
43        }
44
45        for attack_pattern in matrix
46            .collection()
47            .attack_patterns()
48            .filter(|ap| ap.mitre.is_subtechnique == Some(false))
49        {
50            for phase in attack_pattern
51                .base
52                .kill_chain_phases
53                .iter()
54                .filter(|phase| phase.kill_chain_name == "mitre-attack")
55            {
56                if let Some(cell_index) = tactics_by_shortname.get(&phase.phase_name).copied() {
57                    columns[cell_index].1.push(attack_pattern.clone());
58                }
59            }
60        }
61
62        Self {
63            columns,
64            dangling_ids,
65        }
66    }
Source

pub fn courses_of_action<'a>( &'a self, ) -> impl Iterator<Item = Node<'a, CourseOfAction>>

Source

pub fn malware<'a>(&'a self) -> impl Iterator<Item = Node<'a, Malware>>

Source

pub fn matrices<'a>(&'a self) -> impl Iterator<Item = Node<'a, Matrix>>

Examples found in repository?
examples/print_matrix.rs (line 98)
95fn main() {
96    let enterprise = attck::enterprise();
97
98    for matrix in enterprise.matrices() {
99        println!("===== {} =====", matrix.name);
100        let disp = DisplayMatrix::new(matrix);
101        println!("{}", disp);
102        for id in &disp.dangling_ids {
103            eprintln!("Found reference to {} but it was not in the collection", id);
104        }
105    }
106}
Source

pub fn tactics<'a>(&'a self) -> impl Iterator<Item = Node<'a, Tactic>>

Source

pub fn tools<'a>(&'a self) -> impl Iterator<Item = Node<'a, Tool>>

Source

pub fn campaigns<'a>(&'a self) -> impl Iterator<Item = Node<'a, Campaign>>

Source

pub fn identities<'a>(&'a self) -> impl Iterator<Item = Node<'a, Identity>>

Source

pub fn intrusion_sets<'a>( &'a self, ) -> impl Iterator<Item = Node<'a, IntrusionSet>>

Examples found in repository?
examples/actor_lookup.rs (line 47)
45fn search<'store>(store: &'store Collection, term: &str) -> Option<Node<'store, IntrusionSet>> {
46    store
47        .intrusion_sets()
48        .find(|a| a.name() == term || a.aliases().contains(term))
49}
Source

pub fn infrastructure<'a>( &'a self, ) -> impl Iterator<Item = Node<'a, Infrastructure>>

Source

pub fn locations<'a>(&'a self) -> impl Iterator<Item = Node<'a, Location>>

Source

pub fn marking_definitions<'a>( &'a self, ) -> impl Iterator<Item = Node<'a, MarkingDefinition>>

Source

pub fn relationships<'a>( &'a self, ) -> impl Iterator<Item = Node<'a, Relationship>>

Source

pub fn threat_actors<'a>( &'a self, ) -> impl Iterator<Item = Node<'a, ThreatActor>>

Source

pub fn vulnerabilities<'a>( &'a self, ) -> impl Iterator<Item = Node<'a, Vulnerability>>

Trait Implementations§

Source§

impl From<Bundle<Declaration>> for Collection

Source§

fn from(bundle: Bundle<Declaration>) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.