assemblyline_models/datastore/
file.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize};
use serde_with::{DeserializeFromStr, SerializeDisplay};
use struct_metadata::Described;

use crate::{ElasticMeta, ExpandingClassification, SSDeepHash, Sha1, Sha256, Text, MD5};

/// Model of File
#[derive(Debug, Serialize, Deserialize, Described, Clone)]
#[metadata_type(ElasticMeta)]
#[metadata(index=true, store=true)]
pub struct File {
    /// Dotted ASCII representation of the first 64 bytes of the file
    #[metadata(index=false, store=false)]
    pub ascii: String,
    /// Classification of the file
    #[serde(flatten)]
    pub classification: ExpandingClassification,
    /// Entropy of the file
    pub entropy: f32,
    /// Expiry timestamp
    #[metadata(store=false)]
    pub expiry_ts: Option<DateTime<Utc>>,
    /// Is this an image from an Image Result Section?
    #[serde(default)]
    pub is_section_image: bool,
    /// Is this a file generated by a service?
    #[serde(default)]
    pub is_supplementary: bool,
    /// Hex dump of the first 64 bytes of the file
    #[metadata(index=false, store=false)]
    pub hex: String,
    /// List of labels of the file
    #[serde(default)]
    #[metadata(copyto="__text__")]
    pub labels: Vec<String>,
    /// Categories of label
    #[serde(default)]
    pub label_categories: LabelCategories,
    /// MD5 of the file
    #[metadata(copyto="__text__")]
    pub md5: MD5,
    /// Output from libmagic related to the file
    #[metadata(store=false)]
    pub magic: String,
    /// MIME type of the file as identified by libmagic
    #[metadata(store=false)]
    pub mime: Option<String>,
    /// Details about when the file was seen
    #[serde(default)]
    pub seen: Seen,
    /// SHA1 hash of the file
    #[metadata(copyto="__text__")]
    pub sha1: Sha1,
    /// SHA256 hash of the file
    #[metadata(copyto="__text__")]
    pub sha256: Sha256,
    /// Size of the file in bytes
    #[metadata(mapping="integer")]
    pub size: u64,
    /// SSDEEP hash of the file
    #[metadata(store=false)]
    pub ssdeep: SSDeepHash,
    /// Type of file as identified by Assemblyline
    #[serde(rename = "type")]
    #[metadata(copyto="__text__")]
    pub file_type: String,
    /// TLSH hash of the file"
    #[metadata(copyto="__text__")]
    pub tlsh: Option<String>,
    /// Was loaded from the archive
    #[serde(default)]
    #[metadata(index=false, store=false)]
    pub from_archive: bool,

    /// URI structure to speed up specialty file searching
    pub uri_info: Option<URIInfo>,
    /// List of comments made on a file
    #[serde(default)]
    pub comments: Vec<Comment>,
}


/// URI Information Model
#[derive(Debug, Serialize, Deserialize, Described, Clone)]
#[metadata_type(ElasticMeta)]
#[metadata(index=true, store=true)]
pub struct URIInfo {
    /// full URI
    pub uri: String,

    // https://www.rfc-editor.org/rfc/rfc1808.html#section-2.1
    scheme: String,
    netloc: String,
    path: Option<String>,
    params: Option<String>,
    query: Option<String>,
    fragment: Option<String>,

    // Ease-of-use elements
    username: Option<String>,
    password: Option<String>,
    hostname: String,
    port: Option<u16>,
}

/// File Seen Model
#[derive(Debug, Serialize, Deserialize, Described, Clone)]
#[metadata_type(ElasticMeta)]
#[metadata(index=true, store=true)]
pub struct Seen {
    /// How many times have we seen this file?
    #[serde(default = "default_seen_count")]
    #[metadata(mapping="integer")]
    pub count: u64,
    /// First seen timestamp
    #[serde(default = "default_now")]
    pub first: DateTime<Utc>,
    /// Last seen timestamp
    #[serde(default = "default_now")]
    pub last: DateTime<Utc>,
}

fn default_seen_count() -> u64 { 1 }
fn default_now() -> DateTime<Utc> { Utc::now() }

impl Default for Seen {
    fn default() -> Self {
        Self {
            count: default_seen_count(),
            first: default_now(),
            last: default_now()
        }
    }
}


/// Label Categories Model
#[derive(Debug, Serialize, Deserialize, Described, Clone, Default)]
#[serde(default)]
#[metadata_type(ElasticMeta)]
#[metadata(index=true, store=true)]
pub struct LabelCategories {
    /// List of extra informational labels about the file
    pub info: Vec<String>,
    /// List of labels related to the technique used by the file and the signatures that hits on it.
    pub technique: Vec<String>,
    /// List of labels related to attribution of this file (implant name, actor, campain...)
    pub attribution: Vec<String>,
}

/// Comment Model
#[derive(Debug, Serialize, Deserialize, Described, Clone)]
#[metadata_type(ElasticMeta)]
#[metadata(index=true, store=false)]
pub struct Comment {
    /// Comment ID
    pub cid: String,
    /// Username of the user who made the comment
    pub uname: String,
    /// Datetime the comment was made on
    #[serde(default="Utc::now")]
    #[metadata(store=true)]
    pub date: DateTime<Utc>,
    /// Text of the comment written by the author
    pub text: Text,
    /// List of reactions made on a comment
    #[serde(default)]
    pub reactions: Vec<Reaction>,
}

/// Reaction Model
#[derive(Debug, Serialize, Deserialize, Described, Clone)]
#[metadata_type(ElasticMeta)]
#[metadata(index=true, store=false)]
pub struct Reaction {
    /// Icon of the user who made the reaction
    pub icon: ReactionsTypes,
    /// Username of the user who made the reaction
    pub uname: String,
}

#[derive(SerializeDisplay, DeserializeFromStr, strum::Display, strum::EnumString, Described, PartialEq, Eq, Debug, Clone, Copy)]
#[metadata_type(ElasticMeta)]
#[metadata(mapping="keyword")]
#[strum(serialize_all = "snake_case")]
pub enum ReactionsTypes {
    ThumbsUp, 
    ThumbsDown, 
    Love, 
    Smile, 
    Surprised, 
    Party
}