assemblyline_models/datastore/
badlist.rs1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use serde_with::{DeserializeFromStr, SerializeDisplay};
4use struct_metadata::Described;
5use crate::types::classification::unrestricted_classification_string;
6use crate::types::{ClassificationString, ExpandingClassification, SSDeepHash, Sha1, Sha256, UpperString, MD5};
7use crate::{ElasticMeta, Readable};
8
9#[derive(SerializeDisplay, DeserializeFromStr, Clone, Copy, strum::Display, strum::EnumString, Described, Debug, PartialEq, Eq)]
11#[metadata_type(ElasticMeta)]
12#[strum(serialize_all = "lowercase")]
13pub enum BadhashTypes {
14 File,
15 Tag,
16}
17
18#[derive(SerializeDisplay, DeserializeFromStr, Clone, Copy, strum::Display, strum::EnumString, Described, Debug, PartialEq, Eq)]
19#[metadata_type(ElasticMeta)]
20#[strum(serialize_all = "lowercase")]
21pub enum SourceTypes {
22 User,
23 External,
24}
25
26#[derive(Debug, Serialize, Deserialize, Clone, Described, Default, PartialEq, Eq)]
28#[serde(default)]
29#[metadata_type(ElasticMeta)]
30#[metadata(index=true, store=false)]
31pub struct Attribution {
32 #[metadata(copyto="__text__")]
34 pub actor: Option<Vec<UpperString>>,
35 #[metadata(copyto="__text__")]
37 pub campaign: Option<Vec<UpperString>>,
38 #[metadata(copyto="__text__")]
40 pub category: Option<Vec<UpperString>>,
41 #[metadata(copyto="__text__")]
43 pub exploit: Option<Vec<UpperString>>,
44 #[metadata(copyto="__text__")]
46 pub implant: Option<Vec<UpperString>>,
47 #[metadata(copyto="__text__")]
49 pub family: Option<Vec<UpperString>>,
50 #[metadata(copyto="__text__")]
52 pub network: Option<Vec<UpperString>>,
53}
54
55impl Attribution {
56 pub fn update(&mut self, mut other: Attribution) {
57 macro_rules! update_field {($self: ident, $other: ident, $key: ident) => {
58 match &mut $self.$key {
59 Some(data) => {
60 data.append(&mut $other.$key.take().unwrap_or_default());
61 data.sort_unstable();
62 data.dedup();
63 },
64 None => {
65 $self.$key = $other.$key;
66 }
67 };
68 };}
69
70 update_field!(self, other, actor);
71 update_field!(self, other, campaign);
72 update_field!(self, other, category);
73 update_field!(self, other, exploit);
74 update_field!(self, other, implant);
75 update_field!(self, other, family);
76 update_field!(self, other, network);
77 }
78}
79
80#[derive(Debug, Serialize, Deserialize, Clone, Described, Default, PartialEq, Eq)]
82#[serde(default)]
83#[metadata_type(ElasticMeta)]
84#[metadata(index=true, store=true)]
85pub struct Hashes {
86 #[metadata(copyto="__text__")]
88 pub md5: Option<MD5>,
89 #[metadata(copyto="__text__")]
91 pub sha1: Option<Sha1>,
92 #[metadata(copyto="__text__")]
94 pub sha256: Option<Sha256>,
95 #[metadata(copyto="__text__")]
97 pub ssdeep: Option<SSDeepHash>,
98 #[metadata(copyto="__text__")]
100 pub tlsh: Option<String>,
101}
102
103impl Hashes {
104 pub fn update(&mut self, other: Hashes) {
105 macro_rules! update_field {($self: ident, $other: ident, $key: ident) => {
106 $self.$key = $other.$key.or($self.$key.take())
107 };}
108
109 update_field!(self, other, md5);
110 update_field!(self, other, sha1);
111 update_field!(self, other, sha256);
112 update_field!(self, other, ssdeep);
113 update_field!(self, other, tlsh);
114 }
115
116 pub fn label_hash(&self) -> Option<String> {
117 macro_rules! read_field {($self: ident, $key: ident) => {
118 if let Some(val) = &($self.$key) {
119 return Some(val.to_string());
120 }
121 };}
122
123 read_field!(self, sha256);
124 read_field!(self, sha1);
125 read_field!(self, md5);
126 read_field!(self, tlsh);
127 read_field!(self, ssdeep);
128 None
129 }
130}
131
132#[derive(Debug, Serialize, Deserialize, Clone, Described, Default, PartialEq, Eq)]
134#[serde(default)]
135#[metadata_type(ElasticMeta)]
136#[metadata(index=true, store=false)]
137pub struct File {
138 #[metadata(store=true, copyto="__text__")]
140 pub name: Vec<String>,
141 pub size: Option<i64>,
143 #[serde(rename="type")]
145 pub file_type: Option<String>,
146}
147
148
149#[derive(Debug, Serialize, Deserialize, Clone, Described, PartialEq, Eq)]
151#[metadata_type(ElasticMeta)]
152#[metadata(index=true, store=false)]
153pub struct Source {
154 #[serde(default="unrestricted_classification_string")]
156 pub classification: ClassificationString,
157 #[metadata(store=true)]
159 pub name: String,
160 pub reason: Vec<String>,
162 #[serde(rename="type")]
164 pub source_type: SourceTypes,
165}
166
167#[derive(Debug, Serialize, Deserialize, Clone, Described, PartialEq, Eq)]
169#[metadata_type(ElasticMeta)]
170#[metadata(index=true, store=true)]
171pub struct Tag {
172 #[serde(rename="type")]
174 pub tag_type: String,
175 #[metadata(copyto="__text__")]
177 pub value: String,
178}
179
180
181#[derive(Debug, Serialize, Deserialize, Clone, Described, PartialEq, Eq)]
183#[metadata_type(ElasticMeta)]
184#[metadata(index=true, store=true)]
185pub struct Badlist {
186 #[serde(default="chrono::Utc::now")]
188 pub added: DateTime<Utc>,
189 #[serde(default)]
191 pub attribution: Option<Attribution>,
192 #[serde(flatten)]
194 pub classification: ExpandingClassification,
195 #[serde(default="default_true")]
197 pub enabled: bool,
198 #[serde(default)]
200 pub expiry_ts: Option<DateTime<Utc>>,
201 #[serde(default)]
203 pub hashes: Hashes,
204 #[serde(default)]
206 pub file: Option<File>,
207 pub sources: Vec<Source>,
209 #[serde(default)]
211 pub tag: Option<Tag>,
212 #[serde(rename="type")]
214 pub hash_type: BadhashTypes,
215 #[serde(default="chrono::Utc::now")]
217 pub updated: DateTime<Utc>,
218}
219
220fn default_true() -> bool { true }
221
222impl Readable for Badlist {
223 fn set_from_archive(&mut self, _from_archive: bool) {}
224}
225
226