diff --git a/Cargo.lock b/Cargo.lock
index d3defab5..463389ea 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -295,6 +295,18 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
+[[package]]
+name = "assemblyline-markings"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "de017615511c9997a078ef4558e8f3743361f9dedc748b2c9d3caf49c866c14e"
+dependencies = [
+ "itertools 0.11.0",
+ "serde",
+ "serde_json",
+ "serde_yaml",
+]
+
[[package]]
name = "async-broadcast"
version = "0.7.2"
@@ -3183,6 +3195,15 @@ dependencies = [
"either",
]
+[[package]]
+name = "itertools"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
+dependencies = [
+ "either",
+]
+
[[package]]
name = "itertools"
version = "0.12.1"
@@ -3599,6 +3620,7 @@ name = "malwaredb"
version = "0.1.2-dev"
dependencies = [
"anyhow",
+ "assemblyline-markings",
"bytesize",
"cart_container",
"chrono",
@@ -3632,6 +3654,7 @@ dependencies = [
name = "malwaredb-api"
version = "0.1.2-dev"
dependencies = [
+ "assemblyline-markings",
"chrono",
"hex",
"serde",
@@ -5840,6 +5863,19 @@ dependencies = [
"serde",
]
+[[package]]
+name = "serde_yaml"
+version = "0.9.34+deprecated"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
+dependencies = [
+ "indexmap",
+ "itoa",
+ "ryu",
+ "serde",
+ "unsafe-libyaml",
+]
+
[[package]]
name = "sha1"
version = "0.10.6"
@@ -7017,6 +7053,12 @@ dependencies = [
"subtle",
]
+[[package]]
+name = "unsafe-libyaml"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
+
[[package]]
name = "untrusted"
version = "0.9.0"
diff --git a/Cargo.toml b/Cargo.toml
index b9d4856b..bf7d347a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,6 +16,7 @@ build = "build.rs"
default = []
admin = ["dep:dialoguer", "dep:flate2", "malwaredb-server/admin", "dep:chrono", "dep:walkdir", "dep:zip", "toml/serde"]
admin-gui = ["malwaredb-server/admin", "dep:slint", "dep:slint-build", "futures/executor"]
+assemblyline = ["malwaredb-server/assemblyline"]
sqlite = ["malwaredb-server/sqlite"]
vt = ["malwaredb-server/vt", "dep:malwaredb-virustotal"]
@@ -25,6 +26,7 @@ malwaredb-server = { workspace = true }
malwaredb-types = { workspace = true, features = ["elf", "macho", "office95", "officexml", "pdf", "pe32", "pef", "rtf"] }
anyhow = { workspace = true }
+assemblyline-markings = { workspace = true }
bytesize = { workspace = true, features = ["serde"] }
cart_container = { workspace = true, features = ["md5", "sha1"] }
chrono = { workspace = true, optional = true }
@@ -105,6 +107,7 @@ aes-gcm = { version = "0.10.3", default-features = false }
anyhow = { version = "1.0", default-features = false }
app-memory-usage-fetcher = { version = "0.2.1", default-features = false }
argon2 = { version = "0.5.3", default-features = false }
+assemblyline-markings = { version = "0.1.10", default-features = false }
axum = { version = "0.8.4", default-features = false }
axum-server = { version = "0.7.2", default-features = false }
base64 = { version = "0.22.1", default-features = false }
diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml
index 56da12b4..90993932 100644
--- a/crates/api/Cargo.toml
+++ b/crates/api/Cargo.toml
@@ -11,7 +11,12 @@ keywords.workspace = true
rust-version.workspace = true
categories = ["api-bindings", "data-structures"]
+[features]
+default = []
+assemblyline = ["dep:assemblyline-markings"]
+
[dependencies]
+assemblyline-markings = { workspace = true, optional = true }
chrono = { workspace = true, features = ["serde"] }
hex = { workspace = true, features = ["alloc"] }
serde = { workspace = true, features = ["derive", "std"] }
diff --git a/crates/api/src/assemblyline.rs b/crates/api/src/assemblyline.rs
new file mode 100644
index 00000000..a89b904f
--- /dev/null
+++ b/crates/api/src/assemblyline.rs
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: Apache-2.0
+
+use assemblyline_markings::config::ClassificationMarking;
+use serde::{Deserialize, Serialize};
+
+/// API endpoint for uploading a sample, POST, Authenticated for use by Assemblyline
+pub const UPLOAD_SAMPLE: &str = "/v1/assemblyline/samples/upload";
+
+/// New file sample being sent to `MalwareDB`
+#[derive(Clone, Debug, Deserialize, Serialize)]
+pub struct NewSample {
+ /// The original file name, might not be known
+ pub file_name: String,
+
+ /// ID of the source for this sample
+ pub source_id: u32,
+
+ /// Base64 encoding of the binary file
+ pub file_contents_b64: String,
+
+ /// SHA-256 of the sample being sent, for server-side validation
+ pub sha256: String,
+
+ /// Security control for Assemblyline integration based on
+ pub assemblyline_tlp: ClassificationMarking,
+
+ /// Assemblyline's analysis data
+ pub assemblyline_data: serde_json::Map,
+}
diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs
index ef8a7fea..0bc516be 100644
--- a/crates/api/src/lib.rs
+++ b/crates/api/src/lib.rs
@@ -6,6 +6,9 @@
#![deny(clippy::pedantic)]
#![forbid(unsafe_code)]
+/// Data types and API endpoints for Assemblyline integration
+#[cfg(feature = "assemblyline")]
+pub mod assemblyline;
/// Wrapper for fixed-size hash digests from hex strings
pub mod digest;
diff --git a/crates/server/Cargo.toml b/crates/server/Cargo.toml
index e25ffec1..f2896278 100644
--- a/crates/server/Cargo.toml
+++ b/crates/server/Cargo.toml
@@ -15,6 +15,7 @@ build = "build.rs"
[features]
default = []
admin = []
+assemblyline = ["malwaredb-api/assemblyline"]
sqlite = ["dep:rusqlite"]
vt = ["dep:malwaredb-virustotal", "postgres/with-serde_json-1"]
diff --git a/crates/server/src/db/malwaredb_pg.sql b/crates/server/src/db/malwaredb_pg.sql
index d24002ed..14b44b59 100644
--- a/crates/server/src/db/malwaredb_pg.sql
+++ b/crates/server/src/db/malwaredb_pg.sql
@@ -30,6 +30,8 @@ CREATE TABLE file (
nonce bytea[],
key int REFERENCES encryptionkey(id),
parent bigint REFERENCES file(id),
+ assemblyline_data json,
+ assemblyline_tlp text,
PRIMARY KEY (id)
);
diff --git a/crates/server/src/db/malwaredb_sqlite.sql b/crates/server/src/db/malwaredb_sqlite.sql
index 790991f9..91527041 100644
--- a/crates/server/src/db/malwaredb_sqlite.sql
+++ b/crates/server/src/db/malwaredb_sqlite.sql
@@ -47,7 +47,9 @@ CREATE TABLE file (
confirmedmalicious integer, -- boolean
nonce text, -- hex bytes
key int REFERENCES encryptionkey(id),
- parent int REFERENCES file(id)
+ parent int REFERENCES file(id),
+ assemblyline_data text, -- JSON
+ assemblyline_tlp text
);
diff --git a/src/cli/admin/users.rs b/src/cli/admin/users.rs
index 01943411..b88ab32c 100644
--- a/src/cli/admin/users.rs
+++ b/src/cli/admin/users.rs
@@ -38,6 +38,11 @@ pub struct Create {
/// Create a read-only account, usually for guest access or demonstration
#[arg(short, long, default_value_t = false)]
pub readonly: bool,
+
+ #[cfg(feature = "assemblyline")]
+ /// Classification level allowed for this user
+ #[arg(short, long)]
+ pub classification: String,
}
impl Create {